it is OK from Song_yanguang

[ch569w]Add ch569w arch and board codes, support for uart debug
This commit is contained in:
xuedongliang 2025-06-30 18:48:28 +08:00
commit d5afd37e1d
66 changed files with 12997 additions and 1 deletions

View File

@ -5,7 +5,7 @@ MAKEFLAGS += --no-print-directory
.PHONY:COMPILE_APP COMPILE_KERNEL
riscv_support := kd233 maix-go hifive1-rev-B gapuino gd32vf103-rvstar rv32m1-vega aiit-riscv64-board xidatong-riscv64 edu-riscv64 ch32v307vct6 ch32v208rbt6
riscv_support := kd233 maix-go hifive1-rev-B gapuino gd32vf103-rvstar rv32m1-vega aiit-riscv64-board xidatong-riscv64 edu-riscv64 ch32v307vct6 ch32v208rbt6 ch569w
arm_support += stm32f407-st-discovery stm32f407zgt6 stm32f103-nano nuvoton-m2354 ok1052-c imxrt1176-sbc aiit-arm32-board xidatong-arm32 xiwangtong-arm32 edu-arm32 xishutong-arm32 rzv2l-m33 rzg2ul-m33 imx8mp
emulator_support += hifive1-emulator k210-emulator cortex-m0-emulator cortex-m3-emulator cortex-m4-emulator cortex-m7-emulator

View File

@ -45,6 +45,10 @@ ifeq ($(CONFIG_BOARD_CH32V208RBT6), y)
SRC_DIR := ch32v208rbt6
endif
ifeq ($(CONFIG_BOARD_CH569W), y)
SRC_DIR := ch569w
endif
ifeq ($(CONFIG_BOARD_RV32M1_VEGA),y)
SRC_DIR +=rv32m1-vega
endif

View File

@ -0,0 +1,4 @@
SRC_FILES := boot.S interrupt.c prepare_rhwstack.c interrupt_switch.S switch.S tick.c
SRC_DIR := RVMSIS User
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := core_riscv.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,334 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : core_riscv.c
* Author : WCH
* Version : V1.0.1
* Date : 2023/11/11
* Description : RISC-V V3 Core Peripheral Access Layer Source File for CH56x
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
/*********************************************************************
* @fn __get_MSTATUS
*
* @brief Return the Machine Status Register
*
* @return mstatus value
*/
uint32_t __get_MSTATUS(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mstatus" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MSTATUS
*
* @brief Set the Machine Status Register
*
* @param value - set mstatus value
*
* @return none
*/
void __set_MSTATUS(uint32_t value)
{
__ASM volatile ("csrw mstatus, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MISA
*
* @brief Return the Machine ISA Register
*
* @return misa value
*/
uint32_t __get_MISA(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "misa" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MISA
*
* @brief Set the Machine ISA Register
*
* @param value - set misa value
*
* @return none
*/
void __set_MISA(uint32_t value)
{
__ASM volatile ("csrw misa, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MIE
*
* @brief Return the Machine Interrupt Enable Register
*
* @return mie value
*/
uint32_t __get_MIE(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mie" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MISA
*
* @brief Set the Machine ISA Register
*
* @param value - set mie value
*
* @return none
*/
void __set_MIE(uint32_t value)
{
__ASM volatile ("csrw mie, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MTVEC
*
* @brief Return the Machine Trap-Vector Base-Address Register
*
* @return mtvec value
*/
uint32_t __get_MTVEC(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mtvec" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MTVEC
*
* @brief Set the Machine Trap-Vector Base-Address Register
*
* @param value - set mtvec value
*
* @return none
*/
void __set_MTVEC(uint32_t value)
{
__ASM volatile ("csrw mtvec, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MSCRATCH
*
* @brief Return the Machine Seratch Register
*
* @return mscratch value
*/
uint32_t __get_MSCRATCH(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mscratch" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MSCRATCH
*
* @brief Set the Machine Seratch Register
*
* @param value - set mscratch value
*
* @return none
*/
void __set_MSCRATCH(uint32_t value)
{
__ASM volatile ("csrw mscratch, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MEPC
*
* @brief Return the Machine Exception Program Register
*
* @return mepc value
*/
uint32_t __get_MEPC(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mepc" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MEPC
*
* @brief Set the Machine Exception Program Register
*
* @return mepc value
*/
void __set_MEPC(uint32_t value)
{
__ASM volatile ("csrw mepc, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MCAUSE
*
* @brief Return the Machine Cause Register
*
* @return mcause value
*/
uint32_t __get_MCAUSE(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mcause" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MEPC
*
* @brief Set the Machine Cause Register
*
* @return mcause value
*/
void __set_MCAUSE(uint32_t value)
{
__ASM volatile ("csrw mcause, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MTVAL
*
* @brief Return the Machine Trap Value Register
*
* @return mtval value
*/
uint32_t __get_MTVAL(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mtval" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __set_MTVAL
*
* @brief Set the Machine Trap Value Register
*
* @return mtval value
*/
void __set_MTVAL(uint32_t value)
{
__ASM volatile ("csrw mtval, %0" : : "r" (value) );
}
/*********************************************************************
* @fn __get_MVENDORID
*
* @brief Return Vendor ID Register
*
* @return mvendorid value
*/
uint32_t __get_MVENDORID(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mvendorid" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __get_MARCHID
*
* @brief Return Machine Architecture ID Register
*
* @return marchid value
*/
uint32_t __get_MARCHID(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "marchid" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __get_MIMPID
*
* @brief Return Machine Implementation ID Register
*
* @return mimpid value
*/
uint32_t __get_MIMPID(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mimpid" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __get_MHARTID
*
* @brief Return Hart ID Register
*
* @return mhartid value
*/
uint32_t __get_MHARTID(void)
{
uint32_t result;
__ASM volatile ( "csrr %0," "mhartid" : "=r" (result) );
return (result);
}
/*********************************************************************
* @fn __get_SP
*
* @brief Return SP Register
*
* @return SP value
*/
uint32_t __get_SP(void)
{
uint32_t result;
asm volatile ( "mv %0," "sp" : "=r"(result) : );
return (result);
}

View File

@ -0,0 +1,591 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : core_riscv.h
* Author : WCH
* Version : V1.0.1
* Date : 2023/11/11
* Description : RISC-V V3 Core Peripheral Access Layer Header File for CH56x
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CORE_RISCV_H__
#define __CORE_RISCV_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "CH56xSFR.h"
/* IO definitions */
#ifdef __cplusplus
#define __I volatile /*!< defines 'read only' permissions */
#else
#define __I volatile const /*!< defines 'read only' permissions */
#endif
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
#define RV_STATIC_INLINE static inline
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */
typedef struct __attribute__((packed)) {
__I UINT32 ISR[8];
__I UINT32 IPR[8];
__IO UINT32 ITHRESDR;
__IO UINT32 VTFBADDRR;
__IO UINT32 CFGR;
__I UINT32 GISR;
UINT8 RESERVED0[0x10];
__IO UINT32 VTFADDRR[4];
UINT8 RESERVED1[0x90];
__O UINT32 IENR[8];
UINT8 RESERVED2[0x60];
__O UINT32 IRER[8];
UINT8 RESERVED3[0x60];
__O UINT32 IPSR[8];
UINT8 RESERVED4[0x60];
__O UINT32 IPRR[8];
UINT8 RESERVED5[0x60];
__IO UINT32 IACTR[8];
UINT8 RESERVED6[0xE0];
__IO UINT8 IPRIOR[256];
UINT8 RESERVED7[0x810];
__IO UINT32 SCTLR;
}PFIC_Type;
#define FIBADDRR VTFBADDRR
#define FIOFADDRR VTFADDRR
/* memory mapped structure for SysTick */
typedef struct __attribute__((packed))
{
__IO UINT32 CTLR;
__IO UINT64 CNT;
__IO UINT64 CMP;
__IO UINT32 CNTFG;
}SysTick_Type;
#define PFIC ((PFIC_Type *) 0xE000E000 )
#define SysTick ((SysTick_Type *) 0xE000F000)
#define PFIC_KEY1 ((UINT32)0xFA050000)
#define PFIC_KEY2 ((UINT32)0xBCAF0000)
#define PFIC_KEY3 ((UINT32)0xBEEF0000)
/*********************************************************************
* @fn __enable_irq
* This function is only used for Machine mode.
*
* @brief Enable Global Interrupt
*
* @return none
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __enable_irq()
{
__asm volatile ("csrs mstatus, %0" : : "r" (0x88) );
}
/*********************************************************************
* @fn __disable_irq
* This function is only used for Machine mode.
*
* @brief Disable Global Interrupt
*
* @return none
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __disable_irq()
{
__asm volatile ("csrc mstatus, %0" : : "r" (0x88) );
}
/*********************************************************************
* @fn __NOP
*
* @brief nop
*
* @return none
*/
RV_STATIC_INLINE void __NOP()
{
__asm volatile ("nop");
}
/*********************************************************************
* @fn PFIC_EnableIRQ
*
* @brief Enable Interrupt
*
* @param IRQn - Interrupt Numbers
*
* @return none
*/
RV_STATIC_INLINE void PFIC_EnableIRQ(IRQn_Type IRQn)
{
PFIC->IENR[((UINT32)(IRQn) >> 5)] = (1 << ((UINT32)(IRQn) & 0x1F));
}
/*********************************************************************
* @fn PFIC_DisableIRQ
*
* @brief Disable Interrupt
*
* @param IRQn - Interrupt Numbers
*
* @return none
*/
RV_STATIC_INLINE void PFIC_DisableIRQ(IRQn_Type IRQn)
{
UINT32 t;
t = PFIC->ITHRESDR;
PFIC->ITHRESDR = 0x10;
PFIC->IRER[((UINT32)(IRQn) >> 5)] = (1 << ((UINT32)(IRQn) & 0x1F));
PFIC->ITHRESDR = t;
}
/*********************************************************************
* @fn PFIC_GetStatusIRQ
*
* @brief Get Interrupt Enable State
*
* @param IRQn - Interrupt Numbers
*
* @return 1 - Interrupt Enable
* 0 - Interrupt Disable
*/
RV_STATIC_INLINE UINT32 PFIC_GetStatusIRQ(IRQn_Type IRQn)
{
return((UINT32) ((PFIC->ISR[(UINT32)(IRQn) >> 5] & (1 << ((UINT32)(IRQn) & 0x1F)))?1:0));
}
/*********************************************************************
* @fn PFIC_GetPendingIRQ
*
* @brief Get Interrupt Pending State
*
* @param IRQn - Interrupt Numbers
*
* @return 1 - Interrupt Pending Enable
* 0 - Interrupt Pending Disable
*/
RV_STATIC_INLINE UINT32 PFIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((UINT32) ((PFIC->IPR[(UINT32)(IRQn) >> 5] & (1 << ((UINT32)(IRQn) & 0x1F)))?1:0));
}
/*********************************************************************
* @fn PFIC_SetPendingIRQ
*
* @brief Set Interrupt Pending
*
* @param IRQn - Interrupt Numbers
*
* @return none
*/
RV_STATIC_INLINE void PFIC_SetPendingIRQ(IRQn_Type IRQn){
PFIC->IPSR[((UINT32)(IRQn) >> 5)] = (1 << ((UINT32)(IRQn) & 0x1F));
}
/*********************************************************************
* @fn PFIC_ClearPendingIRQ
*
* @brief Clear Interrupt Pending
*
* @param IRQn - Interrupt Numbers
*
* @return none
*/
RV_STATIC_INLINE void PFIC_ClearPendingIRQ(IRQn_Type IRQn)
{
PFIC->IPRR[((UINT32)(IRQn) >> 5)] = (1 << ((UINT32)(IRQn) & 0x1F));
}
/*********************************************************************
* @fn PFIC_GetActive
*
* @brief Get Interrupt Active State
*
* @param IRQn - Interrupt Numbers
*
* @return 1 - Interrupt Active
* 0 - Interrupt No Active
*/
RV_STATIC_INLINE UINT32 PFIC_GetActive(IRQn_Type IRQn)
{
return((UINT32)((PFIC->IACTR[(UINT32)(IRQn) >> 5] & (1 << ((UINT32)(IRQn) & 0x1F)))?1:0));
}
/*********************************************************************
* @fn PFIC_SetPriority
*
* @brief Set Interrupt Priority
*
* @param IRQn - Interrupt Numbers
* interrupt nesting enable(PFIC->CFGR bit1 = 0)
* priority - bit[7] - Preemption Priority
* bit[6:4] - Sub priority
* bit[3:0] - Reserve
* interrupt nesting disable(PFIC->CFGR bit1 = 1)
* priority - bit[7:4] - Sub priority
* bit[3:0] - Reserve
* @return none
*/
RV_STATIC_INLINE void PFIC_SetPriority(IRQn_Type IRQn, UINT8 priority)
{
PFIC->IPRIOR[(UINT32)(IRQn)] = priority;
}
/*********************************************************************
* @fn __WFI
*
* @brief Wait for Interrupt
*
* @return none
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void)
{
PFIC->SCTLR &= ~(1<<3); // wfi
asm volatile ("wfi");
}
/*********************************************************************
* @fn _SEV
*
* @brief Set Event
*
* @return none
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _SEV(void)
{
PFIC->SCTLR |= (1<<3)|(1<<5);
}
/*********************************************************************
* @fn _WFE
*
* @brief Wait for Events
*
* @return none
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _WFE(void)
{
PFIC->SCTLR |= (1<<3);
asm volatile ("wfi");
}
/*********************************************************************
* @fn __WFE
*
* @brief Wait for Events
*
* @return none
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void)
{
_SEV();
_WFE();
_WFE();
}
/*********************************************************************
* @fn PFIC_SetFastIRQ
*
* @brief Set VTF Interrupt
*
* @param add - VTF interrupt service function base address.
* IRQn - Interrupt Numbers
* num - VTF Interrupt Numbers
*
* @return none
*/
RV_STATIC_INLINE void PFIC_SetFastIRQ(UINT32 addr, IRQn_Type IRQn, UINT8 num){
if(num > 3) return ;
PFIC->VTFBADDRR = addr;
PFIC->VTFADDRR[num] = ((UINT32)IRQn<<24)|(addr&0xfffff);
}
/*********************************************************************
* @fn PFIC_SystemReset
*
* @brief Initiate a system reset request
*
* @return none
*/
RV_STATIC_INLINE void PFIC_SystemReset(void){
PFIC->CFGR = PFIC_KEY3|(1<<7);
}
/*********************************************************************
* @fn PFIC_HaltPushCfg
*
* @brief Enable Hardware Stack
*
* @param NewState - DISABLE or ENABLE
* @return none
*/
RV_STATIC_INLINE void PFIC_HaltPushCfg(FunctionalState NewState)
{
if (NewState != DISABLE)
{
PFIC->CFGR = PFIC_KEY1;
}
else
{
PFIC->CFGR = PFIC_KEY1|(1<<0);
}
}
/*********************************************************************
* @fn PFIC_INTNestCfg
*
* @brief Enable Interrupt Nesting
*
* @param NewState - DISABLE or ENABLE
* @return none
*/
RV_STATIC_INLINE void PFIC_INTNestCfg(FunctionalState NewState)
{
if (NewState != DISABLE)
{
PFIC->CFGR = PFIC_KEY1;
}
else
{
PFIC->CFGR = PFIC_KEY1|(1<<1);
}
}
/*********************************************************************
* @fn __AMOADD_W
*
* @brief Atomic Add with 32bit value
* Atomically ADD 32bit value with value in memory using amoadd.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be ADDed
*
* @return return memory value + add value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOADD_W(volatile int32_t *addr, int32_t value)
{
int32_t result;
__asm volatile ("amoadd.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOAND_W
*
* @brief Atomic And with 32bit value
* Atomically AND 32bit value with value in memory using amoand.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be ANDed
*
* @return return memory value & and value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOAND_W(volatile int32_t *addr, int32_t value)
{
int32_t result;
__asm volatile ("amoand.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOMAX_W
*
* @brief Atomic signed MAX with 32bit value
* Atomically signed max compare 32bit value with value in memory using amomax.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be compared
*
* @return the bigger value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMAX_W(volatile int32_t *addr, int32_t value)
{
int32_t result;
__asm volatile ("amomax.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOMAXU_W
*
* @brief Atomic unsigned MAX with 32bit value
* Atomically unsigned max compare 32bit value with value in memory using amomaxu.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be compared
*
* @return return the bigger value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMAXU_W(volatile uint32_t *addr, uint32_t value)
{
uint32_t result;
__asm volatile ("amomaxu.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOMIN_W
*
* @brief Atomic signed MIN with 32bit value
* Atomically signed min compare 32bit value with value in memory using amomin.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be compared
*
* @return the smaller value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMIN_W(volatile int32_t *addr, int32_t value)
{
int32_t result;
__asm volatile ("amomin.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOMINU_W
*
* @brief Atomic unsigned MIN with 32bit value
* Atomically unsigned min compare 32bit value with value in memory using amominu.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be compared
*
* @return the smaller value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMINU_W(volatile uint32_t *addr, uint32_t value)
{
uint32_t result;
__asm volatile ("amominu.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOOR_W
*
* @brief Atomic OR with 32bit value
* Atomically OR 32bit value with value in memory using amoor.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be ORed
*
* @return return memory value | and value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOOR_W(volatile int32_t *addr, int32_t value)
{
int32_t result;
__asm volatile ("amoor.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
/*********************************************************************
* @fn __AMOSWAP_W
*
* @brief Atomically swap new 32bit value into memory using amoswap.d.
* addr - Address pointer to data, address need to be 4byte aligned
* newval - New value to be stored into the address
*
* @return return the original value in memory
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOSWAP_W(volatile uint32_t *addr, uint32_t newval)
{
uint32_t result;
__asm volatile ("amoswap.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(newval) : "memory");
return result;
}
/*********************************************************************
* @fn __AMOXOR_W
*
* @brief Atomic XOR with 32bit value
* Atomically XOR 32bit value with value in memory using amoxor.d.
* addr - Address pointer to data, address need to be 4byte aligned
* value - value to be XORed
*
* @return return memory value ^ and value
*/
__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOXOR_W(volatile int32_t *addr, int32_t value)
{
int32_t result;
__asm volatile ("amoxor.w %0, %2, %1" : \
"=r"(result), "+A"(*addr) : "r"(value) : "memory");
return *addr;
}
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFFFFFFFFFFF)
#define SysTick_CTRL_RELOAD_Msk (1 << 8)
#define SysTick_CTRL_CLKSOURCE_Msk (1 << 2)
#define SysTick_CTRL_TICKINT_Msk (1 << 1)
#define SysTick_CTRL_ENABLE_Msk (1 << 0)
RV_STATIC_INLINE uint32_t SysTick_Config( UINT64 ticks )
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->CMP = ticks - 1; /* set reload register */
PFIC_EnableIRQ( SysTick_IRQn );
SysTick->CTLR = SysTick_CTRL_RELOAD_Msk |
SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
/* Core_Exported_Functions */
extern uint32_t __get_MSTATUS(void);
extern void __set_MSTATUS(uint32_t value);
extern uint32_t __get_MISA(void);
extern void __set_MISA(uint32_t value);
extern uint32_t __get_MIE(void);
extern void __set_MIE(uint32_t value);
extern uint32_t __get_MTVEC(void);
extern void __set_MTVEC(uint32_t value);
extern uint32_t __get_MSCRATCH(void);
extern void __set_MSCRATCH(uint32_t value);
extern uint32_t __get_MEPC(void);
extern void __set_MEPC(uint32_t value);
extern uint32_t __get_MCAUSE(void);
extern void __set_MCAUSE(uint32_t value);
extern uint32_t __get_MTVAL(void);
extern void __set_MTVAL(uint32_t value);
extern uint32_t __get_MVENDORID(void);
extern uint32_t __get_MARCHID(void);
extern uint32_t __get_MIMPID(void);
extern uint32_t __get_MHARTID(void);
extern uint32_t __get_SP(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,3 @@
SRC_FILES := ch56x_it.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,62 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.c
* Author : WCH
* Version : V1.0.0
* Date : 2023/12/29
* Description : Main Interrupt Service Routines.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "core_riscv.h"
#include "ch56x_it.h"
#include "board.h"
#include <xs_isr.h>
void NMI_Handler(void) __attribute__((interrupt()));
void HardFault_Handler(void) __attribute__((interrupt()));
/*********************************************************************
* @fn NMI_Handler
*
* @brief This function handles NMI exception.
*
* @return none
*/
void NMI_Handler(void)
{
GET_INT_SP();
isrManager.done->incCounter();
KPrintf("NMI_Handler.\n");
isrManager.done->decCounter();
FREE_INT_SP();
}
/*********************************************************************
* @fn HardFault_Handler
*
* @brief This function handles Hard Fault exception.
*
* @return none
*/
void HardFault_Handler(void)
{
GET_INT_SP();
isrManager.done->incCounter();
KPrintf("HardFault_Handler.\n");
KPrintf("mepc :%08x\r\n", __get_MEPC());
KPrintf("mcause:%08x\r\n", __get_MCAUSE());
KPrintf("mtval :%08x\r\n", __get_MTVAL());
extern void ShowTask(void);
extern void ShowMemory(void);
ShowTask();
ShowMemory();
while (1)
;
isrManager.done->decCounter();
FREE_INT_SP();
}

View File

@ -0,0 +1,20 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : This file contains the headers of the interrupt handlers.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_IT_H
#define __CH56x_IT_H
#define GET_INT_SP() asm("csrrw sp,mscratch,sp")
#define FREE_INT_SP() asm("csrrw sp,mscratch,sp")
#endif /* __CH32V20x_IT_H */

View File

@ -0,0 +1,13 @@
#ifndef ARCH_INTERRUPT_H__
#define ARCH_INTERRUPT_H__
#include "stdio.h"
#include <xizi.h>
#define ARCH_MAX_IRQ_NUM 36
#define ARCH_IRQ_NUM_OFFSET 0
int ArchEnableHwIrq(uint32_t irq_num);
int ArchDisableHwIrq(uint32_t irq_num);
#endif

View File

@ -0,0 +1,173 @@
;/********************************** (C) COPYRIGHT *******************************
;* File Name : startup_CH56x.s
;* Author : WCH
;* Version : V1.1
;* Date : 2023/11/11
;* Description : CH56x vector table for eclipse toolchain.
;*********************************************************************************
;* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
;* Attention: This software (modified or not) and binary are used for
;* microcontroller manufactured by Nanjing Qinheng Microelectronics.
;*******************************************************************************/
.section .init,"ax",@progbits
.global _start
.align 1
_start:
j handle_reset
.section .vector,"ax",@progbits
.align 1
_vector_base:
.option norvc;
.word 0
.word 0
j NMI_Handler /* NMI Handler */
j HardFault_Handler /* Hard Fault Handler */
.word 0xf7f9bf11
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
j SysTick_Handler /* SysTick Handler */
.word 0
j SW_Handler /* SW Handler */
.word 0
/* External Interrupts */
j WDOG_IRQHandler /* WDOG */
j TMR0_IRQHandler /* TMR0 */
j GPIO_IRQHandler /* GPIO */
j SPI0_IRQHandler /* SPI0 */
j USBSS_IRQHandler /* USBSS */
j LINK_IRQHandler /* LINK */
j TMR1_IRQHandler /* TMR1 */
j TMR2_IRQHandler /* TMR2 */
j UART0_IRQHandler /* UART0 */
j USBHS_IRQHandler /* USBHS */
j EMMC_IRQHandler /* EMMC */
j DVP_IRQHandler /* DVP */
j HSPI_IRQHandler /* HSPI */
j SPI1_IRQHandler /* SPI1 */
j UART1_IRQHandler /* UART1 */
j UART2_IRQHandler /* UART2 */
j UART3_IRQHandler /* UART3 */
j SERDES_IRQHandler /* SERDES */
j ETH_IRQHandler /* ETH */
j PMT_IRQHandler /* PMT */
j ECDC_IRQHandler /* ECDC */
.option rvc;
.section .text.vector_handler, "ax", @progbits
.weak NMI_Handler
.weak HardFault_Handler
.weak SysTick_Handler
.weak SW_Handler
.weak WDOG_IRQHandler
.weak TMR0_IRQHandler
.weak GPIO_IRQHandler
.weak SPI0_IRQHandler
.weak USBSS_IRQHandler
.weak LINK_IRQHandler
.weak TMR1_IRQHandler
.weak TMR2_IRQHandler
.weak UART0_IRQHandler
.weak USBHS_IRQHandler
.weak EMMC_IRQHandler
.weak DVP_IRQHandler
.weak HSPI_IRQHandler
.weak SPI1_IRQHandler
.weak UART1_IRQHandler
.weak UART2_IRQHandler
.weak UART3_IRQHandler
.weak SERDES_IRQHandler
.weak ETH_IRQHandler
.weak PMT_IRQHandler
.weak ECDC_IRQHandler
NMI_Handler:
HardFault_Handler:
SysTick_Handler:
SW_Handler:
WDOG_IRQHandler:
TMR0_IRQHandler:
GPIO_IRQHandler:
SPI0_IRQHandler:
USBSS_IRQHandler:
LINK_IRQHandler:
TMR1_IRQHandler:
TMR2_IRQHandler:
UART0_IRQHandler:
USBHS_IRQHandler:
EMMC_IRQHandler:
DVP_IRQHandler:
HSPI_IRQHandler:
SPI1_IRQHandler:
UART1_IRQHandler:
UART2_IRQHandler:
UART3_IRQHandler:
SERDES_IRQHandler:
ETH_IRQHandler:
PMT_IRQHandler:
ECDC_IRQHandler:
1:
j 1b
.section .text.handle_reset,"ax",@progbits
.weak handle_reset
.align 1
handle_reset:
.option push
.option norelax
la gp, __global_pointer$
.option pop
1:
la sp, _eusrstack
2:
/* Load data section from flash to RAM */
la a0, _data_lma
la a1, _data_vma
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Clear bss section */
la a0, _sbss
la a1, _ebss
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
/* Clear dmadata section */
/*
la a0, _dmadata_start
la a1, _dmadata_end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
*/
/* leave all interrupt disabled */
li t0, 0x1800
csrw mstatus, t0
/* Configure entry address mode */
la t0, _vector_base
ori t0, t0, 1
csrw mtvec, t0
la t0, entry
csrw mepc, t0
mret

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-09 WCH the first version
*/
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef CPUPORT_H__
#define CPUPORT_H__
/* bytes of register width */
//#define ARCH_RISCV_FPU
#define ARCH_RISCV_FPU_S
#ifdef ARCH_CPU_64BIT
#define STORE sd
#define LOAD ld
#define StoreDS "sd"
#define LoadDS "ld"
#define REGBYTES 8
#define RegLength 8
#define RegLengthS "8"
#else
#define STORE sw
#define LOAD lw
#define StoreDS "sw"
#define LoadDS "lw"
#define RegLength 4
#define REGBYTES 4
#define RegLengthS "4"
#endif
/* FPU */
#ifdef ARCH_RISCV_FPU
#ifdef ARCH_RISCV_FPU_D
#define FSTORE fsd
#define FLOAD fld
#define FREGBYTES 8
#endif
#ifdef ARCH_RISCV_FPU_S
#define FSTORE fsw
#define FLOAD flw
#define FREGBYTES 4
#endif
#endif
#endif

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xs_assign.h>
#include <xs_base.h>
#include <xs_isr.h>
#include <xs_ktask.h>
#include "core_riscv.h"
#ifdef TASK_ISOLATION
#include <xs_service.h>
#endif
extern x_ubase interrupt_from_sp;
extern x_ubase interrupt_to_sp;
extern x_ubase interrupt_new_task;
void sw_setpend(void)
{
SysTick->CNTFG |= (1 << 0);
}
void sw_clearpend(void)
{
SysTick->CNTFG &= ~(1 << 0);
}
x_base DisableLocalInterrupt()
{
x_base level;
asm volatile ("csrrci %0, mstatus, 8" : "=r"(level));
return level;
}
void EnableLocalInterrupt(x_base level)
{
asm volatile ("csrw mstatus, %0" :: "r"(level));
}
int ArchEnableHwIrq(uint32_t irq_num)
{
PFIC_SetPriority(irq_num, 1);
PFIC_EnableIRQ(irq_num);
}
int ArchDisableHwIrq(uint32_t irq_num)
{
PFIC_DisableIRQ(irq_num);
}
struct ExceptionStackFrame
{
uint64_t x1;
uint64_t x2;
uint64_t x3;
uint64_t x4;
uint64_t x5;
uint64_t x6;
uint64_t x7;
uint64_t x8;
uint64_t x9;
uint64_t x10;
uint64_t x11;
uint64_t x12;
uint64_t x13;
uint64_t x14;
uint64_t x15;
uint64_t x16;
uint64_t x17;
uint64_t x18;
uint64_t x19;
uint64_t x20;
uint64_t x21;
uint64_t x22;
uint64_t x23;
uint64_t x24;
uint64_t x25;
uint64_t x26;
uint64_t x27;
uint64_t x28;
uint64_t x29;
uint64_t x30;
uint64_t x31;
};
void PrintStackFrame(uintptr_t * sp)
{
struct ExceptionStackFrame * esf = (struct ExceptionStackFrame *)(sp+1);
KPrintf("\n=================================================================\n");
KPrintf("x1 (ra : Return address ) ==> 0x%08x%08x\n", esf->x1 >> 32 , esf->x1 & UINT32_MAX);
KPrintf("x2 (sp : Stack pointer ) ==> 0x%08x%08x\n", esf->x2 >> 32 , esf->x2 & UINT32_MAX);
KPrintf("x3 (gp : Global pointer ) ==> 0x%08x%08x\n", esf->x3 >> 32 , esf->x3 & UINT32_MAX);
KPrintf("x4 (tp : Task pointer ) ==> 0x%08x%08x\n", esf->x4 >> 32 , esf->x4 & UINT32_MAX);
KPrintf("x5 (t0 : Temporary ) ==> 0x%08x%08x\n", esf->x5 >> 32 , esf->x5 & UINT32_MAX);
KPrintf("x6 (t1 : Temporary ) ==> 0x%08x%08x\n", esf->x6 >> 32 , esf->x6 & UINT32_MAX);
KPrintf("x7 (t2 : Temporary ) ==> 0x%08x%08x\n", esf->x7 >> 32 , esf->x7 & UINT32_MAX);
KPrintf("x8 (s0/fp: Save register,frame pointer ) ==> 0x%08x%08x\n", esf->x8 >> 32 , esf->x8 & UINT32_MAX);
KPrintf("x9 (s1 : Save register ) ==> 0x%08x%08x\n", esf->x9 >> 32 , esf->x9 & UINT32_MAX);
KPrintf("x10(a0 : Function argument,return value) ==> 0x%08x%08x\n", esf->x10 >> 32 , esf->x10 & UINT32_MAX);
KPrintf("x11(a1 : Function argument,return value) ==> 0x%08x%08x\n", esf->x11 >> 32 , esf->x11 & UINT32_MAX);
KPrintf("x12(a2 : Function argument ) ==> 0x%08x%08x\n", esf->x12 >> 32 , esf->x12 & UINT32_MAX);
KPrintf("x13(a3 : Function argument ) ==> 0x%08x%08x\n", esf->x13 >> 32 , esf->x13 & UINT32_MAX);
KPrintf("x14(a4 : Function argument ) ==> 0x%08x%08x\n", esf->x14 >> 32 , esf->x14 & UINT32_MAX);
KPrintf("x15(a5 : Function argument ) ==> 0x%08x%08x\n", esf->x15 >> 32 , esf->x15 & UINT32_MAX);
KPrintf("x16(a6 : Function argument ) ==> 0x%08x%08x\n", esf->x16 >> 32 , esf->x16 & UINT32_MAX);
KPrintf("x17(a7 : Function argument ) ==> 0x%08x%08x\n", esf->x17 >> 32 , esf->x17 & UINT32_MAX);
KPrintf("x18(s2 : Save register ) ==> 0x%08x%08x\n", esf->x18 >> 32 , esf->x18 & UINT32_MAX);
KPrintf("x19(s3 : Save register ) ==> 0x%08x%08x\n", esf->x19 >> 32 , esf->x19 & UINT32_MAX);
KPrintf("x20(s4 : Save register ) ==> 0x%08x%08x\n", esf->x20 >> 32 , esf->x20 & UINT32_MAX);
KPrintf("x21(s5 : Save register ) ==> 0x%08x%08x\n", esf->x21 >> 32 , esf->x21 & UINT32_MAX);
KPrintf("x22(s6 : Save register ) ==> 0x%08x%08x\n", esf->x22 >> 32 , esf->x22 & UINT32_MAX);
KPrintf("x23(s7 : Save register ) ==> 0x%08x%08x\n", esf->x23 >> 32 , esf->x23 & UINT32_MAX);
KPrintf("x24(s8 : Save register ) ==> 0x%08x%08x\n", esf->x24 >> 32 , esf->x24 & UINT32_MAX);
KPrintf("x25(s9 : Save register ) ==> 0x%08x%08x\n", esf->x25 >> 32 , esf->x25 & UINT32_MAX);
KPrintf("x26(s10 : Save register ) ==> 0x%08x%08x\n", esf->x26 >> 32 , esf->x26 & UINT32_MAX);
KPrintf("x27(s11 : Save register ) ==> 0x%08x%08x\n", esf->x27 >> 32 , esf->x27 & UINT32_MAX);
KPrintf("x28(t3 : Temporary ) ==> 0x%08x%08x\n", esf->x28 >> 32 , esf->x28 & UINT32_MAX);
KPrintf("x29(t4 : Temporary ) ==> 0x%08x%08x\n", esf->x29 >> 32 , esf->x29 & UINT32_MAX);
KPrintf("x30(t5 : Temporary ) ==> 0x%08x%08x\n", esf->x30 >> 32 , esf->x30 & UINT32_MAX);
KPrintf("x31(t6 : Temporary ) ==> 0x%08x%08x\n", esf->x31 >> 32 , esf->x31 & UINT32_MAX);
KPrintf("=================================================================\n");
}
void HwInterruptcontextSwitch(x_ubase from_sp, x_ubase to_sp, struct TaskDescriptor* new_task, void* context) {
interrupt_from_sp = (x_ubase)from_sp;
interrupt_to_sp = (x_ubase)to_sp;
interrupt_new_task = (x_ubase)new_task;
sw_setpend();
}

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023/01/17 WangShun The first version
* 2023/03/19 Flyingcys Add riscv_32e support
* 2023/08/09 HPMicro Fix the issue t0 was modified unexpectedly before being saved
*/
#define __ASSEMBLY__
#include "cpuport.h"
.section .text.entry, "ax"
#if defined(SOC_SERIES_GD32VF103V)
.align 6
#else
.align 2
#endif
.global SW_Handler
SW_Handler:
csrci mstatus, 0x8
#ifdef ARCH_RISCV_FPU
addi sp, sp, -32 * FREGBYTES
FSTORE f0, 0 * FREGBYTES(sp)
FSTORE f1, 1 * FREGBYTES(sp)
FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
FSTORE f6, 6 * FREGBYTES(sp)
FSTORE f7, 7 * FREGBYTES(sp)
FSTORE f8, 8 * FREGBYTES(sp)
FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
FSTORE f11, 11 * FREGBYTES(sp)
FSTORE f12, 12 * FREGBYTES(sp)
FSTORE f13, 13 * FREGBYTES(sp)
FSTORE f14, 14 * FREGBYTES(sp)
FSTORE f15, 15 * FREGBYTES(sp)
FSTORE f16, 16 * FREGBYTES(sp)
FSTORE f17, 17 * FREGBYTES(sp)
FSTORE f18, 18 * FREGBYTES(sp)
FSTORE f19, 19 * FREGBYTES(sp)
FSTORE f20, 20 * FREGBYTES(sp)
FSTORE f21, 21 * FREGBYTES(sp)
FSTORE f22, 22 * FREGBYTES(sp)
FSTORE f23, 23 * FREGBYTES(sp)
FSTORE f24, 24 * FREGBYTES(sp)
FSTORE f25, 25 * FREGBYTES(sp)
FSTORE f26, 26 * FREGBYTES(sp)
FSTORE f27, 27 * FREGBYTES(sp)
FSTORE f28, 28 * FREGBYTES(sp)
FSTORE f29, 29 * FREGBYTES(sp)
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)
#endif
/* save all from thread context */
#ifndef __riscv_32e
addi sp, sp, -32 * REGBYTES
#else
addi sp, sp, -16 * REGBYTES
#endif
STORE x5, 5 * REGBYTES(sp)
STORE x1, 1 * REGBYTES(sp)
/* Mandatory set the MPIE of mstatus */
li t0, 0x80
STORE t0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
#endif
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
/* switch to interrupt stack */
csrrw sp,mscratch,sp
/* clear interrupt */
jal sw_clearpend
/* switch to from thread stack */
csrrw sp,mscratch,sp
csrr a0, mepc
STORE a0, 0 * REGBYTES(sp)
la t0, interrupt_from_sp
LOAD t1, 0(t0)
STORE sp, 0(t1)
la t0, interrupt_to_sp
LOAD t1, 0(t0)
LOAD sp, 0(t1)
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
1:
LOAD x1, 1 * REGBYTES(sp)
/* Set the mode after MRET */
li t0, 0x1800
csrs mstatus, t0
LOAD t0, 2 * REGBYTES(sp)
csrs mstatus, t0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
#else
addi sp, sp, 16 * REGBYTES
#endif
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp)
FLOAD f1, 1 * FREGBYTES(sp)
FLOAD f2, 2 * FREGBYTES(sp)
FLOAD f3, 3 * FREGBYTES(sp)
FLOAD f4, 4 * FREGBYTES(sp)
FLOAD f5, 5 * FREGBYTES(sp)
FLOAD f6, 6 * FREGBYTES(sp)
FLOAD f7, 7 * FREGBYTES(sp)
FLOAD f8, 8 * FREGBYTES(sp)
FLOAD f9, 9 * FREGBYTES(sp)
FLOAD f10, 10 * FREGBYTES(sp)
FLOAD f11, 11 * FREGBYTES(sp)
FLOAD f12, 12 * FREGBYTES(sp)
FLOAD f13, 13 * FREGBYTES(sp)
FLOAD f14, 14 * FREGBYTES(sp)
FLOAD f15, 15 * FREGBYTES(sp)
FLOAD f16, 16 * FREGBYTES(sp)
FLOAD f17, 17 * FREGBYTES(sp)
FLOAD f18, 18 * FREGBYTES(sp)
FLOAD f19, 19 * FREGBYTES(sp)
FLOAD f20, 20 * FREGBYTES(sp)
FLOAD f21, 21 * FREGBYTES(sp)
FLOAD f22, 22 * FREGBYTES(sp)
FLOAD f23, 23 * FREGBYTES(sp)
FLOAD f24, 24 * FREGBYTES(sp)
FLOAD f25, 25 * FREGBYTES(sp)
FLOAD f26, 26 * FREGBYTES(sp)
FLOAD f27, 27 * FREGBYTES(sp)
FLOAD f28, 28 * FREGBYTES(sp)
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp)
addi sp, sp, 32 * FREGBYTES
#endif
mret

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "cpuport.h"
#include <board.h>
#include <xs_base.h>
#include <xs_ktask.h>
#include <xs_isr.h>
#ifdef TASK_ISOLATION
#include "encoding.h"
#include <stdint.h>
#include <xs_isolation.h>
#endif
volatile x_ubase interrupt_from_sp = 0;
volatile x_ubase interrupt_to_sp = 0;
volatile x_ubase interrupt_new_task = 0;
struct StackRegisterContext
{
x_ubase epc;
x_ubase ra;
x_ubase mstatus;
x_ubase gp;
x_ubase tp;
x_ubase t0;
x_ubase t1;
x_ubase t2;
x_ubase s0_fp;
x_ubase s1;
x_ubase a0;
x_ubase a1;
x_ubase a2;
x_ubase a3;
x_ubase a4;
x_ubase a5;
x_ubase a6;
x_ubase a7;
x_ubase s2;
x_ubase s3;
x_ubase s4;
x_ubase s5;
x_ubase s6;
x_ubase s7;
x_ubase s8;
x_ubase s9;
x_ubase s10;
x_ubase s11;
x_ubase t3;
x_ubase t4;
x_ubase t5;
x_ubase t6;
/* float register */
#ifdef ARCH_RISCV_FPU
x_ubase f0; /* f0 */
x_ubase f1; /* f1 */
x_ubase f2; /* f2 */
x_ubase f3; /* f3 */
x_ubase f4; /* f4 */
x_ubase f5; /* f5 */
x_ubase f6; /* f6 */
x_ubase f7; /* f7 */
x_ubase f8; /* f8 */
x_ubase f9; /* f9 */
x_ubase f10; /* f10 */
x_ubase f11; /* f11 */
x_ubase f12; /* f12 */
x_ubase f13; /* f13 */
x_ubase f14; /* f14 */
x_ubase f15; /* f15 */
x_ubase f16; /* f16 */
x_ubase f17; /* f17 */
x_ubase f18; /* f18 */
x_ubase f19; /* f19 */
x_ubase f20; /* f20 */
x_ubase f21; /* f21 */
x_ubase f22; /* f22 */
x_ubase f23; /* f23 */
x_ubase f24; /* f24 */
x_ubase f25; /* f25 */
x_ubase f26; /* f26 */
x_ubase f27; /* f27 */
x_ubase f28; /* f28 */
x_ubase f29; /* f29 */
x_ubase f30; /* f30 */
x_ubase f31; /* f31 */
#endif
};
uint8 KTaskStackSetup(struct TaskDescriptor *task)
{
struct StackRegisterContext *stack_contex;
int i;
task->stack_point = (uint8 *)ALIGN_MEN_DOWN((x_ubase)(task->task_base_info.stack_start + task->task_base_info.stack_depth), RegLength);
task->stack_point -= sizeof(struct StackRegisterContext);
stack_contex = (struct StackRegisterContext *)task->stack_point;
for (i = 0; i < sizeof(struct StackRegisterContext) / sizeof(x_ubase); i++)
((x_ubase *)stack_contex)[i] = 0xfadeface;
#ifdef SEPARATE_COMPILE
if (task->task_dync_sched_member.isolation_flag == 1) {
stack_contex->ra = (unsigned long)USERSPACE->us_taskquit;
} else {
stack_contex->ra = (x_ubase)KTaskQuit;
}
#else
stack_contex->ra = (x_ubase)KTaskQuit;
#endif
stack_contex->a0 = (x_ubase)task->task_base_info.func_param;
stack_contex->epc = (x_ubase)task->task_base_info.func_entry;
#ifdef TASK_ISOLATION
stack_contex->tp = (x_ubase)task;
if(task->task_dync_sched_member.isolation_flag == 1)
stack_contex->mstatus = 0x00006080;
else
#endif
/* force to machine mode(MPP=11) and set MPIE to 1 */
#ifdef ARCH_RISCV_FPU
stack_contex->mstatus = 0x7880;
#else
stack_contex->mstatus = 0x1880;
#endif
return EOK;
}
#ifdef TASK_ISOLATION
void RestoreMstatus(uintptr_t *sp)
{
struct TaskDescriptor *tid;
tid = (struct TaskDescriptor *)(sp[4]);
if(tid->task_dync_sched_member.isolation_flag == 1 && tid->task_dync_sched_member.isolation_status == 0){
CLEAR_CSR(mstatus, (MSTATUS_MPP));
#ifdef MOMERY_PROTECT_ENABLE
mem_access.Load(tid->task_dync_sched_member.isolation);
#endif
}else{
SET_CSR(mstatus, MSTATUS_MPP);
}
}
#endif

View File

@ -0,0 +1,310 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/10/28 Bernard The unify RISC-V porting implementation
* 2018/12/27 Jesven Add SMP support
* 2020/11/20 BalanceTWK Add FPU support
* 2022/12/28 WangShun Add macro to distinguish whether FPU is supported
* 2023/03/19 Flyingcys Add riscv_32e support
*/
#define __ASSEMBLY__
#include "cpuport.h"
#ifdef RT_USING_SMP
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
#endif
/*
* rt_base_t rt_hw_interrupt_disable(void);
*/
.globl hw_interrupt_disable
hw_interrupt_disable:
csrrci a0, mstatus, 8
ret
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.globl hw_interrupt_enable
hw_interrupt_enable:
csrw mstatus, a0
ret
/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
* #else
* void rt_hw_context_switch_to(rt_ubase_t to);
* #endif
* a0 --> to
* a1 --> to_thread
*/
.global SwitchKtaskContextTo
SwitchKtaskContextTo:
la t0, _eusrstack
//#ifdef SOC_RISCV_FAMILY_CH32
addi t0, t0, -512 // for ch32
//#endif /* SOC_RISCV_FAMILY_CH32 */
csrw mscratch,t0
LOAD sp, (a0)
//#ifdef RT_USING_SMP
mv a0, a1
call RestoreCpusLockStatus
//#endif
LOAD a0, 2 * REGBYTES(sp)
csrw mstatus, a0
j SwitchKTaskContextExit
/*
* #ifdef RT_USING_SMP
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
* #else
* void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
* #endif
*
* a0 --> from
* a1 --> to
* a2 --> to_thread
*/
.globl SwitchKtaskContext
SwitchKtaskContext:
/* saved from thread context
* x1/ra -> sp(0)
* x1/ra -> sp(1)
* mstatus.mie -> sp(2)
* x(i) -> sp(i-4)
*/
#ifdef ARCH_RISCV_FPU
addi sp, sp, -32 * FREGBYTES
FSTORE f0, 0 * FREGBYTES(sp)
FSTORE f1, 1 * FREGBYTES(sp)
FSTORE f2, 2 * FREGBYTES(sp)
FSTORE f3, 3 * FREGBYTES(sp)
FSTORE f4, 4 * FREGBYTES(sp)
FSTORE f5, 5 * FREGBYTES(sp)
FSTORE f6, 6 * FREGBYTES(sp)
FSTORE f7, 7 * FREGBYTES(sp)
FSTORE f8, 8 * FREGBYTES(sp)
FSTORE f9, 9 * FREGBYTES(sp)
FSTORE f10, 10 * FREGBYTES(sp)
FSTORE f11, 11 * FREGBYTES(sp)
FSTORE f12, 12 * FREGBYTES(sp)
FSTORE f13, 13 * FREGBYTES(sp)
FSTORE f14, 14 * FREGBYTES(sp)
FSTORE f15, 15 * FREGBYTES(sp)
FSTORE f16, 16 * FREGBYTES(sp)
FSTORE f17, 17 * FREGBYTES(sp)
FSTORE f18, 18 * FREGBYTES(sp)
FSTORE f19, 19 * FREGBYTES(sp)
FSTORE f20, 20 * FREGBYTES(sp)
FSTORE f21, 21 * FREGBYTES(sp)
FSTORE f22, 22 * FREGBYTES(sp)
FSTORE f23, 23 * FREGBYTES(sp)
FSTORE f24, 24 * FREGBYTES(sp)
FSTORE f25, 25 * FREGBYTES(sp)
FSTORE f26, 26 * FREGBYTES(sp)
FSTORE f27, 27 * FREGBYTES(sp)
FSTORE f28, 28 * FREGBYTES(sp)
FSTORE f29, 29 * FREGBYTES(sp)
FSTORE f30, 30 * FREGBYTES(sp)
FSTORE f31, 31 * FREGBYTES(sp)
#endif
#ifndef __riscv_32e
addi sp, sp, -32 * REGBYTES
#else
addi sp, sp, -16 * REGBYTES
#endif
STORE sp, (a0)
STORE x1, 0 * REGBYTES(sp)
STORE x1, 1 * REGBYTES(sp)
csrr a0, mstatus
andi a0, a0, 8
beqz a0, save_mpie
li a0, 0x80
save_mpie:
STORE a0, 2 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
#ifndef __riscv_32e
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
#endif
/* restore to thread context
* sp(0) -> epc;
* sp(1) -> ra;
* sp(i) -> x(i+2)
*/
LOAD sp, (a1)
#ifdef RT_USING_SMP
mv a0, a2
call rt_cpus_lock_status_restore
#endif /*RT_USING_SMP*/
j SwitchKTaskContextExit
#ifdef RT_USING_SMP
/*
* void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
*
* a0 --> context
* a1 --> from
* a2 --> to
* a3 --> to_thread
*/
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
STORE a0, 0(a1)
LOAD sp, 0(a2)
move a0, a3
call rt_cpus_lock_status_restore
j rt_hw_context_switch_exit
#endif
.global SwitchKTaskContextExit
SwitchKTaskContextExit:
#ifdef RT_USING_SMP
#ifdef RT_USING_SIGNALS
mv a0, sp
csrr t0, mhartid
/* switch interrupt stack of current cpu */
la sp, __stack_start__
addi t1, t0, 1
li t2, __STACKSIZE__
mul t1, t1, t2
add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
call rt_signal_check
mv sp, a0
#endif
#endif
/* resw ra to mepc */
LOAD a0, 0 * REGBYTES(sp)
csrw mepc, a0
LOAD x1, 1 * REGBYTES(sp)
#ifdef ARCH_RISCV_FPU
li t0, 0x7800
#else
li t0, 0x1800
#endif
csrw mstatus, t0
LOAD a0, 2 * REGBYTES(sp)
csrs mstatus, a0
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
#ifndef __riscv_32e
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
addi sp, sp, 32 * REGBYTES
#else
addi sp, sp, 16 * REGBYTES
#endif
#ifdef ARCH_RISCV_FPU
FLOAD f0, 0 * FREGBYTES(sp)
FLOAD f1, 1 * FREGBYTES(sp)
FLOAD f2, 2 * FREGBYTES(sp)
FLOAD f3, 3 * FREGBYTES(sp)
FLOAD f4, 4 * FREGBYTES(sp)
FLOAD f5, 5 * FREGBYTES(sp)
FLOAD f6, 6 * FREGBYTES(sp)
FLOAD f7, 7 * FREGBYTES(sp)
FLOAD f8, 8 * FREGBYTES(sp)
FLOAD f9, 9 * FREGBYTES(sp)
FLOAD f10, 10 * FREGBYTES(sp)
FLOAD f11, 11 * FREGBYTES(sp)
FLOAD f12, 12 * FREGBYTES(sp)
FLOAD f13, 13 * FREGBYTES(sp)
FLOAD f14, 14 * FREGBYTES(sp)
FLOAD f15, 15 * FREGBYTES(sp)
FLOAD f16, 16 * FREGBYTES(sp)
FLOAD f17, 17 * FREGBYTES(sp)
FLOAD f18, 18 * FREGBYTES(sp)
FLOAD f19, 19 * FREGBYTES(sp)
FLOAD f20, 20 * FREGBYTES(sp)
FLOAD f21, 21 * FREGBYTES(sp)
FLOAD f22, 22 * FREGBYTES(sp)
FLOAD f23, 23 * FREGBYTES(sp)
FLOAD f24, 24 * FREGBYTES(sp)
FLOAD f25, 25 * FREGBYTES(sp)
FLOAD f26, 26 * FREGBYTES(sp)
FLOAD f27, 27 * FREGBYTES(sp)
FLOAD f28, 28 * FREGBYTES(sp)
FLOAD f29, 29 * FREGBYTES(sp)
FLOAD f30, 30 * FREGBYTES(sp)
FLOAD f31, 31 * FREGBYTES(sp)
addi sp, sp, 32 * FREGBYTES
#endif
mret

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xs_ktick.h>
#include <xs_isr.h>
#include <xs_assign.h>
#include "core_riscv.h"
#include "CH56x_common.h"
#include "ch56x_it.h"
extern void KTaskOsAssignAfterIrq(void *);
void SysTick_Handler(void) __attribute__((interrupt()));
void SysTick_Handler(void)
{
GET_INT_SP();
/* enter interrupt */
x_base level;
level = DisableLocalInterrupt();
isrManager.done->incCounter();
EnableLocalInterrupt(level);
SysTick->CNTFG &= ~(1 << 1);
TickAndTaskTimesliceUpdate();
KTaskOsAssignAfterIrq(NONE);
/* leave interrupt */
level = DisableLocalInterrupt();
isrManager.done->decCounter();
EnableLocalInterrupt(level);
FREE_INT_SP();
}

View File

@ -0,0 +1,31 @@
mainmenu "XiZi_IIoT Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config KERNEL_DIR
string
option env="KERNEL_ROOT"
default "../.."
config BOARD_CH569W
bool
select ARCH_RISCV
default y
source "$KERNEL_DIR/arch/Kconfig"
menu "ch569w feature"
source "$BSP_DIR/third_party_driver/Kconfig"
endmenu
menu "Hardware feature"
source "$KERNEL_DIR/resources/Kconfig"
endmenu
source "$KERNEL_DIR/Kconfig"

View File

@ -0,0 +1,6 @@
SRC_FILES := board.c
SRC_DIR := third_party_driver
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,78 @@
# 1. 简介
| 硬件 | 描述 |
| --------- | ----------------------------------------- |
| 芯片型号 | CH569W |
| CPU | 单核RISC-V3A |
| 主频 | 120MHz |
| 片内SRAM | 32/64/96KB 可配置的 128 位宽 SRAMRAMX |
| 片内FLASH | 448KB 用户应用程序存储区 CodeFlash |
| 外设 | UART等 |
# 2. 克隆代码
将XiUOS的源代码克隆下来
```bash
git clone https://gitlink.org.cn/xuos/xiuos.git
```
# 3. 下载编译工具链
编译环境Ubuntu 20.04.6 LTS
编译工具链riscv-none-embed-gccxpack-riscv-none-embed-gcc-8.2.0-3.1
编译工具链可到Github进行下载https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v8.2.0-3.1/xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz
下载完成后将其移动到`/opt`目录下,并进行解压:
```bash
sudo tar -xvzf xpack-riscv-none-embed-gcc-8.2.0-3.1-linux-x64.tgz
```
# 4. 编译
## 方式1推荐
可以在`Ubiquitous/XiZi_IIoT`目录下创建文件`script.sh`,内容如下:
```sh
#! /bin/env sh
export CROSS_COMPILE=/opt/xPacks/riscv-none-embed-gcc/8.2.0-3.1/bin/riscv-none-embed-
make BOARD=ch569w distclean # 将之前的编译生成文件清空
make BOARD=ch569w menuconfig
make BOARD=ch569w
```
创建之后,在命令行移动到`XiZi-IIOT`目录下,键入`./script`运行该脚本。
经过Kconfig配置、编译后即可在`Ubiquitous/XiZi_IIoT/build`目录中生成`XiZi-ch569w.bin`文件将该文件拷贝至Windows侧待下一步进行烧录。
> [!CAUTION]
>
> 如果`make BOARD=ch569w menuconfig`显示【无法找到`kconfig-mconf`】,需要先安装`ncurses-devel`和`kconfig-mconf`,如下:
>
> ```bash
> sudo apt install libncurses5-dev kconfig-frontends
# 5. 烧录
1. 沁恒微电子官网下载 WCHISPTool.exe 工具进行 bin 文件下载到芯片 flash 的操作。CH569W 芯片需要进入下载模式才能使用 ISP 工具下载代码,一般使用 USB 方式下载代码最为方便。
2. 将 CH569W 评估板使用 USB 插头对插头线和计算机连接起来。如图,打开 ISP 下载工具,芯片信号选择 CH569下载方式选择 USB将 CH569W 评估板断电,然后将下载配置脚(出厂默认为 PA5原理图上的HD0接地后对评估板上电此时 ISP 工具的 USB 设备列表中将显示新连上来的 CH569W 芯片。最后点击“下载”,即可使程序下载到评估版上的主芯片。
<img src="imgs/image_shaolukaifabanpaizhao.jpg" alt="image_shaolukaifabanpaizhao" style="zoom:30%;" />
<img src="imgs/image_shaoluruanjianjietu.png" alt="image_shaoluruanjianjietu" style="zoom:50%;" />
# 6. 启动
烧录完成后,并且将串口连接至电脑。
将评估板上电重新,即可看到操作系统启动的信息,如下:
![image_xitongqidongrizhi](imgs/image_xitongqidongrizhi.png)

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file board.c
* @brief support ch569 init configure and start-up
* @version 1.0
* @author AIIT XUOS Lab
* @date 2025-04-07
*/
#include <device.h>
#include <stdint.h>
#include <xizi.h>
#include "CH56x_common.h"
#include "connect_uart.h"
#include "board.h"
void InitBoardHardware()
{
SystemInit(FREQ_SYS);
Delay_Init(FREQ_SYS);
SysTick_Config(FREQ_SYS / TICK_PER_SECOND);
PFIC_EnableIRQ(SWI_IRQn);
/* initialize memory system */
InitBoardMemory(MEMORY_START_ADDRESS, (void *)MEMORY_END_ADDRESS);
#ifdef BSP_USING_UART
InitHwUart();
InstallConsole("uart1", SERIAL_DRV_NAME_1, SERIAL_1_DEVICE_NAME_0);
KPrintf("\nconsole init completed.\n");
#endif
KPrintf("memory address range: [0x%08x - 0x%08x] ssize: %x\n", (x_ubase)MEMORY_START_ADDRESS,
(x_ubase)MEMORY_END_ADDRESS, MEMORY_STACK_SIZE);
KPrintf("board init done.\n");
KPrintf("start kernel...\n");
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file board.h
* @brief define ch569 init configure and start-up function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2025-04-07
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include <stdint.h>
#include "CH56xSFR.h"
extern uint32_t _ebss;
extern uint32_t __stack_size;
#define MEMORY_START_ADDRESS ((void *)&_ebss)
//#define MEMORY_END_ADDRESS ((void *)(BA_RAM) + (SZ_RAM))
#define MEMORY_END_ADDRESS ((void *)(BA_RAMX) + (SZ_RAMX))
#define MEMORY_STACK_SIZE (&__stack_size)
void InitBoardHardware(void);
#endif /* __BOARD_H__ */

View File

@ -0,0 +1,18 @@
export MARCH := rv32imac
# export CFLAGS := -march=$(MARCH) -mabi=ilp32 -msmall-data-limit=8 -msave-restore -Os -g
export CFLAGS := -march=rv32imac -mabi=ilp32 -msmall-data-limit=8 -mno-save-restore -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g -std=gnu99
export AFLAGS := -march=$(MARCH) -mabi=ilp32 -x assembler-with-cpp -ggdb
export LFLAGS := -march=$(MARCH) -mabi=ilp32 -nostartfiles -Wl,--gc-sections,-Map=XiZi-ch569w.map,-cref,-u,_start -T $(BSP_ROOT)/link.ld
export APPLFLAGS := -nostartfiles -Wl,--gc-sections,-Map=XiZi-app.map,-cref,-u, -T $(BSP_ROOT)/link_userspace.lds
export CXXFLAGS := -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-common # -std=gnu99
export DEFINES := -DDEBUG=1
export ARCH = risc-v
export MCU = CH569W

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,209 @@
ENTRY( _start )
__stack_size = 2048;
PROVIDE( _stack_size = __stack_size );
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
RAMX (xrw) : ORIGIN = 0x20020000, LENGTH = 96K
}
SECTIONS
{
.init :
{
_sinit = .;
. = ALIGN(4);
KEEP(*(SORT_NONE(.init)))
. = ALIGN(4);
_einit = .;
} >FLASH AT>FLASH
.vector :
{
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH
.hclib :
{
. = ALIGN(4);
*ISPEM569.o(*)
. = ALIGN(4);
}
.text :
{
. = ALIGN(4);
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
*(.gnu.linkonce.t.*)
. = ALIGN(4);
/* section information for shell */
. = ALIGN(4);
_shell_command_start = .;
KEEP (*(shellCommand))
_shell_command_end = .;
. = ALIGN(4);
PROVIDE(__ctors_start__ = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE(__ctors_end__ = .);
. = ALIGN(4);
__isrtbl_idx_start = .;
KEEP(*(.isrtbl.idx))
__isrtbl_start = .;
KEEP(*(.isrtbl))
__isrtbl_end = .;
. = ALIGN(4);
PROVIDE(g_service_table_start = ABSOLUTE(.));
KEEP(*(.g_service_table))
PROVIDE(g_service_table_end = ABSOLUTE(.));
*(.gnu.linkonce.t.*)
} >FLASH AT>FLASH
.fini :
{
KEEP(*(SORT_NONE(.fini)))
. = ALIGN(4);
} >FLASH AT>FLASH
PROVIDE( _etext = . );
PROVIDE( _eitcm = . );
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH AT>FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH AT>FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH AT>FLASH
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >FLASH AT>FLASH
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >FLASH AT>FLASH
.dalign :
{
. = ALIGN(4);
PROVIDE(_data_vma = .);
} >RAMX AT>FLASH
.dlalign :
{
. = ALIGN(4);
PROVIDE(_data_lma = .);
} >FLASH AT>FLASH
.data :
{
*(.gnu.linkonce.r.*)
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
PROVIDE( _edata = .);
} >RAMX AT>FLASH
.bss :
{
. = ALIGN(4);
PROVIDE( _sbss = .);
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss*)
*(.gnu.linkonce.b.*)
*(COMMON*)
. = ALIGN(4);
PROVIDE( _ebss = .);
} >RAMX AT>FLASH
PROVIDE( _end = _ebss);
PROVIDE( end = . );
/*
.DMADATA :
{
. = ALIGN(16);
PROVIDE( _dmadata_start = .);
*(.dmadata*)
*(.dmadata.*)
. = ALIGN(16);
PROVIDE( _dmadata_end = .);
} >RAMX AT>FLASH
*/
.stack ORIGIN(RAMX) + LENGTH(RAMX) - __stack_size :
{
. = ALIGN(4);
PROVIDE(_susrstack = . );
. = . + __stack_size;
PROVIDE( _eusrstack = .);
} >RAMX
}

View File

@ -0,0 +1,7 @@
menuconfig BSP_USING_UART
bool "Using UART device"
default y
select RESOURCES_SERIAL
if BSP_USING_UART
source "$BSP_DIR/third_party_driver/uart/Kconfig"
endif

View File

@ -0,0 +1,7 @@
SRC_DIR := Peripheral
ifeq ($(CONFIG_BSP_USING_UART),y)
SRC_DIR += uart
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_DIR := src
include $(KERNEL_ROOT)/compiler.mk

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_bus8.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_BUS8_H__
#define __CH56x_BUS8_H__
#ifdef __cplusplus
extern "C" {
#endif
#define ADDR_NONE 0x00
#define ADDR_6 0x04
#define ADDR_10 0x08
#define ADDR_15 0x0c
#define WIDTH_3 0x00
#define WIDTH_5 0x10
#define WIDTH_9 0x20
#define WIDTH_16 0x30
#define HOLD_2 0x00
#define HOLD_3 0x40
#define SETUP_2 0x00
#define SETUP_3 0x80
void BUS8_Init(UINT8 addroe, UINT8 width, UINT8 hold, UINT8 setup);
#ifdef __cplusplus
}
#endif
#endif // __CH56x_BUS8_H__

View File

@ -0,0 +1,44 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_clk.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_CLK_H__
#define __CH56x_CLK_H__
#ifdef __cplusplus
extern "C" {
#endif
enum
{
CLK_SOURCE_PLL_15MHz = 15, //Power-on default
CLK_SOURCE_PLL_30MHz = 30,
CLK_SOURCE_PLL_60MHz = 60,
CLK_SOURCE_PLL_80MHz = 80,
CLK_SOURCE_PLL_96MHz = 96,
CLK_SOURCE_PLL_120MHz = 120,
};
void SystemInit(uint32_t systemclck); /* System clock initialization */
UINT32 GetSysClock( void ); /* Get the current system clock */
#ifdef __cplusplus
}
#endif
#endif // __CH56x_CLK_H__

View File

@ -0,0 +1,62 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_COMM.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_COMM_H__
#define __CH56x_COMM_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "string.h"
#include "core_riscv.h"
#include "CH56x_sys.h"
#include "CH56x_clk.h"
#include "CH56x_uart.h"
#include "CH56x_gpio.h"
#include "CH56x_pwm.h"
#include "CH56x_timer.h"
#include "CH56x_spi.h"
#include "CH56x_hspi.h"
#include "CH56x_dvp.h"
#include "CH56x_bus8.h"
#include "CH56x_ecdc.h"
#include "CH56x_pwr.h"
#include "CH56x_emmc.h"
#include "CH56x_eth.h"
/* UART Printf Definition */
#define Debug_UART0 0
#define Debug_UART1 1
#define Debug_UART2 2
#define Debug_UART3 3
/* SystemCoreClock */
#ifndef FREQ_SYS
#define FREQ_SYS 80000000
#endif
#define DelayMs(x) mDelaymS(x)
#define DelayUs(x) mDelayuS(x)
#ifdef __cplusplus
}
#endif
#endif // __CH56x_COMM_H__

View File

@ -0,0 +1,72 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_dvp.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_DVP_H__
#define __CH56x_DVP_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief DVP Data Mode
*/
typedef enum
{
Video_Mode = 0,
JPEG_Mode,
}DVP_Data_ModeTypeDef;
/**
* @brief DVP DMA
*/
typedef enum
{
DVP_DMA_Disable = 0,
DVP_DMA_Enable,
}DVP_DMATypeDef;
/**
* @brief DVP FLAG and FIFO Reset
*/
typedef enum
{
DVP_FLAG_FIFO_RESET_Disable = 0,
DVP_FLAG_FIFO_RESET_Enable,
}DVP_FLAG_FIFO_RESETTypeDef;
/**
* @brief DVP RX Reset
*/
typedef enum
{
DVP_RX_RESET_Disable = 0,
DVP_RX_RESET_Enable,
}DVP_RX_RESETTypeDef;
void DVP_INTCfg( UINT8 s, UINT8 i );
void DVP_Mode( UINT8 s, DVP_Data_ModeTypeDef i);
void DVP_Cfg( DVP_DMATypeDef s, DVP_FLAG_FIFO_RESETTypeDef i, DVP_RX_RESETTypeDef j);
#ifdef __cplusplus
}
#endif
#endif // __CH56x_DVP_H__

View File

@ -0,0 +1,67 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_ecdc.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_ECDC_H__
#define __CH56x_ECDC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Encryption and decryption mode */
#define MODE_SM4_ECB 0
#define MODE_AES_ECB 1
#define MODE_SM4_CTR 2
#define MODE_AES_CTR 3
/* endian mode */
#define MODE_BIG_ENDIAN 1
#define MODE_LITTLE_ENDIAN 0
/* key length */
#define KEYLENGTH_128BIT 0
#define KEYLENGTH_192BIT 1
#define KEYLENGTH_256BIT 2
/* Encryption and decryption speed */
#define ECDCCLK_DISABLE 1
#define ECDCCLK_240MHZ 2
#define ECDCCLK_160MHZ 3
/* direction and mode */
#define SELFDMA_ENCRY 0x84
#define SELFDMA_DECRY 0x8c
#define SINGLEREGISTER_ENCRY PERIPHERAL_TO_RAM_ENCRY
#define SINGLEREGISTER_DECRY PERIPHERAL_TO_RAM_DECRY
#define PERIPHERAL_TO_RAM_ENCRY 0x02
#define PERIPHERAL_TO_RAM_DECRY 0x0a
#define RAM_TO_PERIPHERAL_ENCRY 0x04
#define RAM_TO_PERIPHERAL_DECRY 0x0c
void ECDC_Init( UINT8 ecdcmode, UINT8 clkmode, UINT8 keylen, PUINT32 pkey, PUINT32 pcount );
void ECDC_SetKey( PUINT32 pkey, UINT8 keylen );
void ECDC_SetCount( PUINT32 pcount );
void ECDC_Excute( UINT8 excutemode, UINT8 endianmode );
void ECDC_SingleRegister( PUINT32 pWdatbuff, PUINT32 pRdatbuff );
void ECDC_SelfDMA( UINT32 ram_addr, UINT32 ram_len );
void ECDC_RloadCount( UINT8 excutemode, UINT8 endianmode, PUINT32 pcount );
#ifdef __cplusplus
}
#endif
#endif // __CH56x_ECDC_H__

View File

@ -0,0 +1,147 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_emmc.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_EMMC_H__
#define __CH56x_EMMC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* CMD code */
#define EMMC_CMD0 0 /* rsp:none */
#define EMMC_CMD1 1 /* rsp:R3 SEND_OP_COND */
#define EMMC_CMD2 2 /* rsp:R2 ALL_SEND_CID */
#define EMMC_CMD3 3 /* rsp:R6 SEND_RELATIVE_ADDR */
#define EMMC_CMD6 6 /* rsp: */
#define EMMC_CMD7 7 /* rsp:Rb1 */
#define EMMC_CMD8 8 /* rsp:R7 */
#define EMMC_CMD9 9 /* rsp: */
#define EMMC_CMD11 11 /* rsp: */
#define EMMC_CMD12 12 /* rsp: */
#define EMMC_CMD13 13
#define EMMC_CMD17 17 /* rsp: READ_SINGLE_BLOCK */
#define EMMC_CMD18 18 /* rsp: READ_MULTIPLE_BLOCK */
#define EMMC_CMD24 24 /* rsp: WRITE_BLOCK */
#define EMMC_CMD25 25 /* rsp: WRITE_MILTIPLE_BLOCK */
#define EMMC_CMD41 41 /* rsp: */
#define EMMC_CMD55 55 /* rsp: */
/* operation status */
#define CMD_NULL 0x00
#define CMD_SUCCESS 0x01
#define CMD_FAILED 0x02
#define OP_SUCCESS CMD_SUCCESS
#define OP_FAILED CMD_FAILED
#define OP_INVALID_ADD 0x21 //invalid address
/* connection status*/
#define EMMCDisconnect 0
#define EMMCConnect 1
/* operation on EMMC */
#define EMMCCardSatus_Idle 0 /* EMMC on free */
#define EMMCCardSatus_SendSingleReadCmd 1 /* send command:read single */
#define EMMCCardSatus_SendMultReadCmd 2 /* send command:read multiple */
#define EMMCCardSatus_SendSingleWriteCmd 3 /* send command:write single */
#define EMMCCardSatus_SendMultWriteCmd 4 /* send command:write multiple */
#define EMMCCardSatus_SingleReadData 5 /* on reading single */
#define EMMCCardSatus_MultReadData 6 /* on reading multiple */
#define EMMCCardSatus_SingleWriteData 7 /* on writing single */
#define EMMCCardSatus_MultWriteData 8 /* on writing multiple */
#define EMMCCardSatus_SingleReadComp 9 /* read single done */
#define EMMCCardSatus_MultReadComp 10 /* read multiple done */
#define EMMCCardSatus_SingleWriteComp 11 /* write single done */
#define EMMCCardSatus_MultWriteComp 12 /* write multiple done */
/* EMMC type */
#define EMMCIO_CAPACITY_SD_CARD_V1_1 0
#define EMMCIO_CAPACITY_SD_CARD_V2_0 1
#define EMMCIO_HIGH_CAPACITY_SD_CARD 2
/* EMMC useful voltage type */
#define EMMCCardVolt_3_3 (1<<0)
#define EMMCCardVolt_1_8 (1<<1)
#define EMMCPLUGIN (1<<12)
/* EMMC information */
typedef struct _EMMC_PARAMETER{
UINT8 EMMCLinkSatus; // connecting type
UINT8 EMMCCardSatus; // EMMC operation status
UINT8 EMMCType; // EMMC type
UINT8 EMMCVoltageMode; // EMMC useful voltage type bit0:3.3v bit1:1.8v
UINT32 EMMC_CID[4];
UINT32 EMMC_CSD[4];
UINT16 EMMC_RCA; // relative address
UINT16 EMMCSecSize; // single section capacity
UINT32 EMMCSecNum; // capacity of section
UINT8 EMMCOpErr; // latest error status
}EMMC_PARAMETER, *PSD_PARAMETER;
//#define RESP_TYPE_48 (0<<8)
#define RESP_TYPE_136 (1<<8)
#define RESP_TYPE_48 (2<<8)
#define RESP_TYPE_R1b (3<<8)
/* EMMC CLK SET */
#define EMMCCLK_48 10
#define EMMCCLK_60 8
#define EMMCCLK_80 6
#define EMMCCLK_96 5
#define LOWEMMCCLK 0x1F
#define DEFAULTSDCLK EMMCCLK_48
#define HIGHEMMCCLK EMMCCLK_96
/* EMMCIO power */
#define EMMCIOSetPower_3_3 (R32_PA_CLR |= (1<<3)) /* PA3=0 SDIO power = 3.3v */
#define EMMCIOSetPower_1_8 (R32_PA_OUT |= (1<<3)) /* PA3=1 SDIO EMMC*/
#define EMMCSendCmd(a, b) {R32_EMMC_ARGUMENT = a; R16_EMMC_CMD_SET = b;}
#define EMMCDat0Sta (R32_EMMC_STATUS&(1<<17)) /* EMMC data0 status */
extern UINT8 EMMCIO0Init( void );
extern UINT8 CheckCMDComp( PSD_PARAMETER pEMMCPara );
extern void EMMCResetIdle( PSD_PARAMETER pEMMCPara );
extern UINT8 EMMCReadOCR( PSD_PARAMETER pEMMCPara);
extern UINT8 EMMCReadCID( PSD_PARAMETER pEMMCPara );
extern UINT8 EMMCSetRCA( PSD_PARAMETER pEMMCPara );
extern UINT8 EMMCReadCSD( PSD_PARAMETER pEMMCPara );
extern UINT8 SelectEMMCCard(PSD_PARAMETER pEMMCPara);
extern UINT8 ReadEMMCStatus(PSD_PARAMETER pEMMCPara);
extern UINT8 EMMCSetBusWidth(PSD_PARAMETER pEMMCPara, UINT8 bus_mode);
extern UINT8 EMMCSetHighSpeed(PSD_PARAMETER pEMMCPara);
extern UINT8 EMMCCardConfig( PSD_PARAMETER pEMMCPara );
extern UINT8 EMMCIOTransErrorDeal( PSD_PARAMETER pEMMCPara );
extern UINT8 EMMCCardReadEXCSD( PSD_PARAMETER pEMMCPara, PUINT8 pRdatbuf );
extern UINT8 AES_EMMCWriteMulSec( PSD_PARAMETER pEMMCPara, PUINT32 pReqnum, PUINT32 pWdatbuf, UINT32 Lbaaddr, UINT8 excutemode, UINT8 endianmode, PUINT32 pcount);
extern UINT8 AES_EMMCReadMulSec( PSD_PARAMETER pEMMCPara, PUINT32 pReqnum, PUINT32 pRdatbuf, UINT32 Lbaaddr, UINT8 excutemode, UINT8 endianmode, PUINT32 pcount);
UINT8 EMMCCardReadOneSec( PSD_PARAMETER pEMMCPara, PUINT8 pRdatbuf, UINT32 Lbaaddr );
UINT8 EMMCCardReadMulSec( PSD_PARAMETER pEMMCPara, PUINT16 pReqnum, PUINT8 pRdatbuf, UINT32 Lbaaddr );
UINT8 EMMCCardWriteMulSec( PSD_PARAMETER pEMMCPara, PUINT16 pReqnum, PUINT8 pWdatbuf, UINT32 Lbaaddr );
#ifdef __cplusplus
}
#endif
#endif //__CH56X_EMMC_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,144 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_gpio.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_GPIO_H__
#define __CH56x_GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
#define GPIO_Pin_0 (0x00000001) /*!< Pin 0 selected */
#define GPIO_Pin_1 (0x00000002) /*!< Pin 1 selected */
#define GPIO_Pin_2 (0x00000004) /*!< Pin 2 selected */
#define GPIO_Pin_3 (0x00000008) /*!< Pin 3 selected */
#define GPIO_Pin_4 (0x00000010) /*!< Pin 4 selected */
#define GPIO_Pin_5 (0x00000020) /*!< Pin 5 selected */
#define GPIO_Pin_6 (0x00000040) /*!< Pin 6 selected */
#define GPIO_Pin_7 (0x00000080) /*!< Pin 7 selected */
#define GPIO_Pin_8 (0x00000100) /*!< Pin 8 selected */
#define GPIO_Pin_9 (0x00000200) /*!< Pin 9 selected */
#define GPIO_Pin_10 (0x00000400) /*!< Pin 10 selected */
#define GPIO_Pin_11 (0x00000800) /*!< Pin 11 selected */
#define GPIO_Pin_12 (0x00001000) /*!< Pin 12 selected */
#define GPIO_Pin_13 (0x00002000) /*!< Pin 13 selected */
#define GPIO_Pin_14 (0x00004000) /*!< Pin 14 selected */
#define GPIO_Pin_15 (0x00008000) /*!< Pin 15 selected */
#define GPIO_Pin_16 (0x00010000) /*!< Pin 16 selected */
#define GPIO_Pin_17 (0x00020000) /*!< Pin 17 selected */
#define GPIO_Pin_18 (0x00040000) /*!< Pin 18 selected */
#define GPIO_Pin_19 (0x00080000) /*!< Pin 19 selected */
#define GPIO_Pin_20 (0x00100000) /*!< Pin 20 selected */
#define GPIO_Pin_21 (0x00200000) /*!< Pin 21 selected */
#define GPIO_Pin_22 (0x00400000) /*!< Pin 22 selected */
#define GPIO_Pin_23 (0x00800000) /*!< Pin 23 selected */
#define GPIO_Pin_24 (0x01000000) /*!< PinB23 selected */
#define GPIO_Pin_All (0xFFFFFFFF) /*!< All pins selected */
/**
* @brief GPIO mode structure configuration
*/
typedef enum
{
GPIO_ModeIN_Floating, //floating input
GPIO_ModeIN_PU_NSMT,
GPIO_ModeIN_PD_NSMT,
GPIO_ModeIN_PU_SMT,
GPIO_ModeIN_PD_SMT,
GPIO_Slowascent_PP_8mA,
GPIO_Slowascent_PP_16mA,
GPIO_Highspeed_PP_8mA,
GPIO_Highspeed_PP_16mA,
GPIO_ModeOut_OP_8mA,
GPIO_ModeOut_OP_16mA,
}GPIOModeTypeDef;
/**
* @brief GPIO interrupt structure configuration
*/
typedef enum
{
GPIO_ITMode_LowLevel, //Low level trigger
GPIO_ITMode_HighLevel, //High level trigger
GPIO_ITMode_FallEdge, //Falling edge trigger
GPIO_ITMode_RiseEdge, //Rising edge trigger
}GPIOITModeTpDef;
/**
* @brief GPIO MCO structure configuration
*/
typedef enum
{
MCO_125 = 0,
MCO_25 = 4,
MCO_2d5 = 0xC,
}MCOMode;
void GPIOA_ModeCfg( UINT32 pin, GPIOModeTypeDef mode ); /* GPIOA port pin mode configuration */
void GPIOB_ModeCfg( UINT32 pin, GPIOModeTypeDef mode ); /* GPIOB port pin mode configuration */
#define GPIOA_ResetBits( pin ) (R32_PA_CLR |= pin) /* GPIOA port pin output set low */
#define GPIOA_SetBits( pin ) (R32_PA_OUT |= pin) /* GPIOA port pin output set high */
#define GPIOB_ResetBits( pin ) (R32_PB_CLR |= pin) /* GPIOB port pin output set low */
#define GPIOB_SetBits( pin ) (R32_PB_OUT |= pin) /* GPIOB port pin output set high */
#define GPIOA_InverseBits( pin ) (R32_PA_OUT ^= pin) /* GPIOA port pin output level flip */
#define GPIOB_InverseBits( pin ) (R32_PB_OUT ^= pin) /* GPIOB port pin output level flip */
#define GPIOA_ReadPort() (R32_PA_PIN) /* The 32-bit data returned by the GPIOA port, the lower 16 bits are valid */
#define GPIOB_ReadPort() (R32_PB_PIN) /* The 32-bit data returned by the GPIOB port, the lower 24 bits are valid */
#define GPIOA_ReadPortPin( pin ) (R32_PA_PIN&pin) /* GPIOA port pin status, 0-pin low level, (!0)-pin high level */
#define GPIOB_ReadPortPin( pin ) (R32_PB_PIN&pin) /* GPIOB port pin status, 0-pin low level, (!0)-pin high level */
void GPIOA_ITModeCfg( UINT32 pin, GPIOITModeTpDef mode ); /* GPIOA pin interrupt mode configuration */
void GPIOB_ITModeCfg( UINT32 pin, GPIOITModeTpDef mode ); /* GPIOB pin interrupt mode configuration */
#define GPIOA_ReadITFlagPort() (R8_GPIO_INT_FLAG) /* Read GPIOA port interrupt flag status */
#define GPIOB_ReadITFlagPort() (R8_GPIO_INT_FLAG) /* Read GPIOB port interrupt flag status */
/*************************************Read Interrupt Bit Flag************************************/
#define GPIOA_2_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x01) /* Read GPIOA port pin interrupt flag status */
#define GPIOA_3_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x02)
#define GPIOA_4_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x04)
#define GPIOB_3_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x08) /* Read GPIOB port pin interrupt flag status */
#define GPIOB_4_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x10)
#define GPIOB_11_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x20)
#define GPIOB_12_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x40)
#define GPIOB_15_ReadITFlagBit( ) (R8_GPIO_INT_FLAG & 0x80)
/*************************************Clear Interrupt Bit Flag************************************/
#define GPIOA_2_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x01) /* Clear the GPIOA port pin interrupt flag status */
#define GPIOA_3_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x02)
#define GPIOA_4_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x04)
#define GPIOB_3_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x08) /* Clear the GPIOB port pin interrupt flag status */
#define GPIOB_4_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x10)
#define GPIOB_11_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x20)
#define GPIOB_12_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x40)
#define GPIOB_15_ClearITFlagBit( ) (R8_GPIO_INT_FLAG = 0x80)
void GPIOPinRemap( UINT8 s, UINT16 perph ); /* Peripheral Function Pin Mapping */
void GPIOMco( UINT8 s, UINT16 freq ); /* MCO function */
#ifdef __cplusplus
}
#endif
#endif // __CH56x_GPIO_H__

View File

@ -0,0 +1,43 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_hspi.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_HSPI_H__
#define __CH56x_HSPI_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief HSPI Mode
*/
typedef enum
{
DOWN_Mode = 0,
UP_Mode,
}HSPI_ModeTypeDef;
void HSPI_Mode( UINT8 s, HSPI_ModeTypeDef i);
void HSPI_INTCfg( UINT8 s, UINT8 i );
#ifdef __cplusplus
}
#endif
#endif // __CH56x_HSPI_H__

View File

@ -0,0 +1,70 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_pwm.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_PWM_H__
#define __CH56x_PWM_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief channel of PWM define
*/
#define CH_PWM0 0x01 // PWM0 channel
#define CH_PWM1 0x02 // PWM1 channel
#define CH_PWM2 0x04 // PWM2 channel
#define CH_PWM3 0x08 // PWM3 channel
/**
* @brief channel of PWM define
*/
typedef enum
{
High_Level = 0, //Default low level, high level is active
Low_Level, //Default high level, low level active
}PWMX_PolarTypeDef;
/**
* @brief Configuration PWM0_3 Cycle size
*/
typedef enum
{
PWMX_Cycle_256 = 0, //256 PWMX cycles
PWMX_Cycle_255, //255 PWMX cycles
}PWMX_CycleTypeDef;
#define PWMX_CLKCfg( d ) (R8_PWM_CLOCK_DIV=d) //PWM Reference Clock Configuration
void PWMX_CycleCfg( PWMX_CycleTypeDef cyc ); //PWM output waveform period configuration
#define PWM0_ActDataWidth( d ) (R8_PWM0_DATA = d) //PWM0 effective data pulse width
#define PWM1_ActDataWidth( d ) (R8_PWM1_DATA = d) //PWM1 effective data pulse width
#define PWM2_ActDataWidth( d ) (R8_PWM2_DATA = d) //PWM2 effective data pulse width
#define PWM3_ActDataWidth( d ) (R8_PWM3_DATA = d) //PWM3 effective data pulse width
//Duty cycle = data valid width/waveform period
void PWMX_ACTOUT( UINT8 ch, UINT8 da, PWMX_PolarTypeDef pr, UINT8 s); //PWM0-3 output waveform configuration
#ifdef __cplusplus
}
#endif
#endif // __CH56x_PWM_H__

View File

@ -0,0 +1,59 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_pwr.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_PWR_H__
#define __CH56x_PWR_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Peripher CLK control bit define
*/
#define BIT_SLP_CLK_TMR0 RB_SLP_CLK_TMR0 /*!< TMR0 peripher clk bit */
#define BIT_SLP_CLK_TMR1 RB_SLP_CLK_TMR1 /*!< TMR1 peripher clk bit */
#define BIT_SLP_CLK_TMR2 RB_SLP_CLK_TMR2 /*!< TMR2 peripher clk bit */
#define BIT_SLP_CLK_PWMX RB_SLP_CLK_PWMX /*!< PWMX peripher clk bit */
#define BIT_SLP_CLK_UART0 RB_SLP_CLK_UART0 /*!< UART0 peripher clk bit */
#define BIT_SLP_CLK_UART1 RB_SLP_CLK_UART1 /*!< UART1 peripher clk bit */
#define BIT_SLP_CLK_UART2 RB_SLP_CLK_UART2 /*!< UART2 peripher clk bit */
#define BIT_SLP_CLK_UART3 RB_SLP_CLK_UART3 /*!< UART3 peripher clk bit */
#define BIT_SLP_CLK_SPI0 RB_SLP_CLK_SPI0 /*!< SPI0 peripher clk bit */
#define BIT_SLP_CLK_SPI1 RB_SLP_CLK_SPI1 /*!< SPI1 peripher clk bit */
#define BIT_SLP_CLK_EMMC RB_SLP_CLK_EMMC /*!< EMMC peripher clk bit */
#define BIT_SLP_CLK_HSPI RB_SLP_CLK_HSPI /*!< HSPI peripher clk bit */
#define BIT_SLP_CLK_USBHS RB_SLP_CLK_USBHS /*!< USBHS peripher clk bit */
#define BIT_SLP_CLK_USBSS RB_SLP_CLK_USBSS /*!< USBSS peripher clk bit */
#define BIT_SLP_CLK_SERD RB_SLP_CLK_SERD /*!< SERD peripher clk bit */
#define BIT_SLP_CLK_DVP RB_SLP_CLK_DVP /*!< DVP peripher clk bit */
#define BIT_SLP_CLK_ETH RB_SLP_CLK_ETH /*!< ETH peripher clk bit */
#define BIT_SLP_CLK_ECDC RB_SLP_CLK_ECDC /*!< ECDC peripher clk bit */
void PWR_PeriphClkCfg( UINT8 s, UINT16 perph ); /* Peripheral Clock Control Bits */
void PWR_PeriphWakeUpCfg( UINT8 s, UINT16 perph ); /* Sleep wakeup source configuration */
void LowPower_Idle( void ); /* Low power consumption - IDLE mode Execute WFI*/
void LowPower_Idle_WFE( void ); /* Low power consumption - IDLE mode Execute WFE*/
void LowPower_Halt( void ); /* Low power consumption - Halt mode Execute WFI*/
void LowPower_Halt_WFE( void ); /* Low power consumption - Halt mode Execute WFE*/
void LowPower_Sleep( void ); /* Low power consumption - Sleep mode Execute WFI*/
void LowPower_Sleep_WFE( void ); /* Low power consumption - Sleep mode Execute WFE*/
#ifdef __cplusplus
}
#endif
#endif // __CH56x_PWR_H__

View File

@ -0,0 +1,118 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_spi.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_SPI_H__
#define __CH56x_SPI_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief SPI0 interrupt bit define
*/
#define SPI0_IT_FST_BYTE RB_SPI_IE_FST_BYTE
#define SPI0_IT_FIFO_OV RB_SPI_IE_FIFO_OV
#define SPI0_IT_DMA_END RB_SPI_IE_DMA_END
#define SPI0_IT_FIFO_HF RB_SPI_IE_FIFO_HF
#define SPI0_IT_BYTE_END RB_SPI_IE_BYTE_END
#define SPI0_IT_CNT_END RB_SPI_IE_CNT_END
/**
* @brief Configuration data mode
*/
typedef enum
{
Mode0_LowBitINFront = 0,
Mode0_HighBitINFront,
Mode3_LowBitINFront,
Mode3_HighBitINFront,
}ModeBitOrderTypeDef;
/**
* @brief Configuration SPI slave mode
*/
typedef enum
{
Mode_DataStream = 0,
Mose_FirstCmd,
}Slave_ModeTypeDef;
/**************** SPI0 */
void SPI0_MasterDefInit( void );
void SPI0_DataMode( ModeBitOrderTypeDef m );
void SPI0_MasterSendByte( UINT8 d );
UINT8 SPI0_MasterRecvByte( void );
void SPI0_MasterTrans( UINT8 *pbuf, UINT16 len );
void SPI0_MasterRecv( UINT8 *pbuf, UINT16 len );
void SPI0_MasterDMATrans( PUINT8 pbuf, UINT16 len);
void SPI0_MasterDMARecv( PUINT8 pbuf, UINT16 len);
void SPI0_SlaveInit( void );
#define SetFirst0Data(d) (R8_SPI0_SLAVE_PRE = d)
void SPI0_SlaveSendByte( UINT8 d );
UINT8 SPI0_SlaveRecvByte( void );
void SPI0_SlaveTrans( UINT8 *pbuf, UINT16 len );
void SPI0_SlaveRecv( PUINT8 pbuf, UINT16 len );
// refer to SPI0 interrupt bit define
#define SPI0_ITCfg(s,f) ((s)?(R8_SPI0_INTER_EN|=f):(R8_SPI0_INTER_EN&=~f))
#define SPI0_GetITFlag(f) (R8_SPI0_INT_FLAG&f)
#define SPI0_ClearITFlag(f) (R8_SPI0_INT_FLAG = f)
/**************** SPI1 */
void SPI1_MasterDefInit( void );
void SPI1_DataMode( ModeBitOrderTypeDef m );
void SPI1_MasterSendByte( UINT8 d );
UINT8 SPI1_MasterRecvByte( void );
void SPI1_MasterTrans( UINT8 *pbuf, UINT16 len );
void SPI1_MasterRecv( UINT8 *pbuf, UINT16 len );
void SPI1_MasterDMATrans( PUINT8 pbuf, UINT16 len);
void SPI1_MasterDMARecv( PUINT8 pbuf, UINT16 len);
void SPI1_SlaveInit( void );
#define SetFirst1Data(d) (R8_SPI1_SLAVE_PRE = d)
void SPI1_SlaveSendByte( UINT8 d );
UINT8 SPI1_SlaveRecvByte( void );
void SPI1_SlaveTrans( UINT8 *pbuf, UINT16 len );
void SPI1_SlaveRecv( PUINT8 pbuf, UINT16 len );
// refer to SPI1 interrupt bit define
#define SPI1_ITCfg(s,f) ((s)?(R8_SPI1_INTER_EN|=f):(R8_SPI1_INTER_EN&=~f))
#define SPI1_GetITFlag(f) (R8_SPI1_INT_FLAG&f)
#define SPI1_ClearITFlag(f) (R8_SPI1_INT_FLAG = f)
#ifdef __cplusplus
}
#endif
#endif // __CH56x_SPI_H__

View File

@ -0,0 +1,64 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_sys.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description : This file contains all the functions prototypes for
* SystemCoreClock, UART Printf , Delay functions .
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_SYS_H__
#define __CH56x_SYS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "CH56xSFR.h"
/**
* @brief SYSTEM Information State
*/
typedef enum
{
INFO_RESET_EN = 2, // RST# Whether the external manual reset input function is enabled
INFO_BOOT_EN, // Whether the system boot program BootLoader is enabled
INFO_DEBUG_EN, // Whether the system simulation debugging interface is enabled
INFO_LOADER, // Whether the current system is in the Bootloader area
}SYS_InfoStaTypeDef;
#define SYS_GetChipID() R8_CHIP_ID /* Get the chip ID class, generally a fixed value */
#define SYS_GetAccessID() R8_SAFE_ACCESS_ID /* Get the security access ID, usually a fixed value */
UINT8 SYS_GetInfoSta( SYS_InfoStaTypeDef i ); /* Get the current system information status */
void Delay_Init(uint32_t systemclck);
void mDelayuS(uint32_t n);
void mDelaymS(uint32_t n);
//refer to SYS_ResetStaTypeDef
#define SYS_GetLastResetSta() (R8_RST_BOOT_STAT&RB_RESET_FLAG) /* Get the last reset status of the system */
void SYS_ResetExecute( void ); /* Perform a system software reset */
#define SYS_ResetKeepBuf( d ) (R8_GLOB_RESET_KEEP = d) /* Not affected by manual reset, software reset, watchdog reset or normal wake-up reset */
//WWDG
#define WWDG_SetCounter( c ) (R8_WDOG_COUNT = c) /* Load the initial value of the watchdog count, incremental */
void WWDG_ITCfg( UINT8 s ); /* Watchdog overflow interrupt enable */
void WWDG_ResetCfg( UINT8 s ); /* Watchdog time-out reset enable */
#define WWDG_GetFlowFlag() (R8_RST_WDOG_CTRL&RB_WDOG_INT_FLAG) /* Get the current watchdog timer overflow flag */
void WWDG_ClearFlag(void); /* Clear watchdog interrupt flag, reload count value can also be cleared */
#ifdef __cplusplus
}
#endif
#endif // __CH56x_SYS_H__

View File

@ -0,0 +1,155 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_timer.ch
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_TIMER_H__
#define __CH56x_TIMER_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Pulse Width Modulation Effective Output Words
*/
typedef enum
{
PWM_Times_1 = 0, // PWM effective output repeats 1 times
PWM_Times_4 = 1, // PWM effective output repeats 4 times
PWM_Times_8 = 2, // PWM effective output repeats 8 times
PWM_Times_16 = 3, // PWM effective output repeats 16 times
}PWM_RepeatTsTypeDef;
/**
* @brief Input Capture Edge Mode
*/
typedef enum
{
CAP_NULL = 0, // not capture
Edge_To_Edge = 1, // between any edge
FallEdge_To_FallEdge = 2, // falling edge to falling edge
RiseEdge_To_RiseEdge = 3, // rising edge to rising edge
}CapModeTypeDef;
/**
* @brief Direct access memory loop mode
*/
typedef enum
{
Mode_Single = 0, // single mode
Mode_LOOP = 1, // cycle mode
}DMAModeTypeDef;
/**
* @brief PWM output polarity
*/
typedef enum
{
high_on_low = 0, // Default low level, high level is active
low_on_high = 1, // Default high level, low level active
}PWM_PolarTypeDef;
/****************** TMR0 */
// Timing and counting
void TMR0_TimerInit( UINT32 t ); /* Timing function initialization */
void TMR0_EXTSignalCounterInit( UINT32 c ); /* External signal counting function initialization */
#define TMR0_GetCurrentCount() R32_TMR0_COUNT /* Get the current count value, 67108864 */
// Pulse Width Modulation Function
#define TMR0_PWMCycleCfg( cyc ) (R32_TMR0_CNT_END=cyc) /* PWM0 channel output waveform period configuration, maximum 67108864 */
void TMR0_PWMInit( PWM_PolarTypeDef pr, PWM_RepeatTsTypeDef ts ); /* PWM0 output initialization */
#define TMR0_PWMActDataWidth( d ) (R32_TMR0_FIFO = d) /* PWM0 effective data pulse width, maximum 67108864 */
// Catch pulse width
#define TMR0_CAPTimeoutCfg( cyc ) (R32_TMR0_CNT_END=cyc) /* CAP0 capture level timeout configuration, maximum 33554432 */
void TMR0_CapInit( CapModeTypeDef cap ); /* External signal capture function initialization */
#define TMR0_CAPGetData() R32_TMR0_FIFO /* Get pulse data */
#define TMR0_CAPDataCounter() R8_TMR0_FIFO_COUNT /* Get the number of currently captured data */
#define TMR0_Disable() (R8_TMR0_CTRL_MOD &= ~RB_TMR_COUNT_EN) /* Close TMR0 */
// refer to TMR0 interrupt bit define
#define TMR0_ITCfg(s,f) ((s)?(R8_TMR0_INTER_EN|=f):(R8_TMR0_INTER_EN&=~f)) /* TMR0 corresponding interrupt bit on and off */
// refer to TMR0 interrupt bit define
#define TMR0_ClearITFlag(f) (R8_TMR0_INT_FLAG = f) /* Clear interrupt flag */
#define TMR0_GetITFlag(f) (R8_TMR0_INT_FLAG&f) /* Query interrupt flag status */
/****************** TMR1 */
// Timing and counting
void TMR1_TimerInit( UINT32 t ); /* Timing function initialization */
void TMR1_EXTSignalCounterInit( UINT32 c ); /* External signal counting function initialization */
#define TMR1_GetCurrentCount() R32_TMR1_COUNT /* Get the current count value, 67108864 */
// Pulse Width Modulation Function
#define TMR1_PWMCycleCfg( cyc ) (R32_TMR1_CNT_END=cyc) /* PWM1 channel output waveform period configuration, maximum 67108864 */
void TMR1_PWMInit( PWM_PolarTypeDef pr, PWM_RepeatTsTypeDef ts ); /* PWM1 output initialization */
#define TMR1_PWMActDataWidth( d ) (R32_TMR1_FIFO = d) /* PWM1 effective data pulse width, maximum 67108864 */
// Catch pulse width
#define TMR1_CAPTimeoutCfg( cyc ) (R32_TMR1_CNT_END=cyc) /* CAP1 capture level timeout configuration, maximum 33554432 */
void TMR1_CapInit( CapModeTypeDef cap ); /* External signal capture function initialization */
#define TMR1_CAPGetData() R32_TMR1_FIFO /* Get pulse data */
#define TMR1_CAPDataCounter() R8_TMR1_FIFO_COUNT /* Get the number of currently captured data */
void TMR1_DMACfg( UINT8 s, UINT16 startAddr, UINT16 endAddr, DMAModeTypeDef m ); /* DMA configuration */
#define TMR1_Disable() (R8_TMR1_CTRL_MOD &= ~RB_TMR_COUNT_EN) /* Close TMR1 */
// refer to TMR1 interrupt bit define
#define TMR1_ITCfg(s,f) ((s)?(R8_TMR1_INTER_EN|=f):(R8_TMR1_INTER_EN&=~f)) /* TMR1 corresponding interrupt bit on and off */
// refer to TMR1 interrupt bit define
#define TMR1_ClearITFlag(f) (R8_TMR1_INT_FLAG = f) /* Clear interrupt flag */
#define TMR1_GetITFlag(f) (R8_TMR1_INT_FLAG&f) /* Query interrupt flag status */
/****************** TMR2 */
// Timing and counting
void TMR2_TimerInit( UINT32 t ); /* Timing function initialization */
void TMR2_EXTSignalCounterInit( UINT32 c ); /* External signal counting function initialization */
#define TMR2_GetCurrentCount() R32_TMR2_COUNT /* Get the current count value, 67108864 */
// Pulse Width Modulation Function
#define TMR2_PWMCycleCfg( cyc ) (R32_TMR2_CNT_END=cyc) /* PWM2 channel output waveform period configuration, maximum 67108864 */
void TMR2_PWMInit( PWM_PolarTypeDef pr, PWM_RepeatTsTypeDef ts ); /* PWM2 output initialization */
#define TMR2_PWMActDataWidth( d ) (R32_TMR2_FIFO = d) /* PWM2 effective data pulse width, maximum 67108864 */
// Catch pulse width
#define TMR2_CAPTimeoutCfg( cyc ) (R32_TMR2_CNT_END=cyc) /* CAP2 capture level timeout configuration, maximum 33554432 */
void TMR2_CapInit( CapModeTypeDef cap ); /* External signal capture function initialization */
#define TMR2_CAPGetData() R32_TMR2_FIFO /* Get pulse data */
#define TMR2_CAPDataCounter() R8_TMR2_FIFO_COUNT /* Get the number of currently captured data */
void TMR2_DMACfg( UINT8 s, UINT16 startAddr, UINT16 endAddr, DMAModeTypeDef m ); /* DMA configuration */
#define TMR2_Disable() (R8_TMR2_CTRL_MOD &= ~RB_TMR_COUNT_EN) /* Close TMR2 */
// refer to TMR2 interrupt bit define
#define TMR2_ITCfg(s,f) ((s)?(R8_TMR2_INTER_EN|=f):(R8_TMR2_INTER_EN&=~f)) /* TMR2 corresponding interrupt bit on and off */
// refer to TMR2 interrupt bit define
#define TMR2_ClearITFlag(f) (R8_TMR2_INT_FLAG = f) /* Clear interrupt flag */
#define TMR2_GetITFlag(f) (R8_TMR2_INT_FLAG & f) /* Query interrupt flag status */
#ifdef __cplusplus
}
#endif
#endif // __CH56x_TIMER_H__

View File

@ -0,0 +1,136 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_uart.h
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#ifndef __CH56x_UART_H__
#define __CH56x_UART_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Line Error Status Definition
*/
#define STA_ERR_BREAK RB_LSR_BREAK_ERR // Data Interval Error
#define STA_ERR_FRAME RB_LSR_FRAME_ERR // DataFrame error
#define STA_ERR_PAR RB_LSR_PAR_ERR // Parity bit error
#define STA_ERR_FIFOOV RB_LSR_OVER_ERR // Receive Data Overflow
#define STA_TXFIFO_EMP RB_LSR_TX_FIFO_EMP // The current send FIFO is empty, you can continue to fill the send data
#define STA_TXALL_EMP RB_LSR_TX_ALL_EMP // All currently sent data has been sent
#define STA_RECV_DATA RB_LSR_DATA_RDY // Data is currently received
/**
* @brief Serial port byte trigger configuration
*/
typedef enum
{
UART_1BYTE_TRIG = 0, // 1 byte trigger
UART_2BYTE_TRIG = 1, // 2 byte trigger
UART_4BYTE_TRIG = 2, // 4 byte trigger
UART_7BYTE_TRIG = 3 , // 7 byte trigger
}UARTByteTRIGTypeDef;
/****************** UART0 */
void UART0_DefInit( void ); /* Serial port default initialization configuration */
void UART0_BaudRateCfg( UINT32 baudrate ); /* Serial port baud rate configuration */
void UART0_ByteTrigCfg( UARTByteTRIGTypeDef b ); /* Serial byte trigger interrupt configuration */
void UART0_INTCfg( UINT8 s, UINT8 i ); /* Serial port interrupt configuration */
void UART0_Reset( void ); /* Serial port software reset */
#define UART0_CLR_RXFIFO() (R8_UART0_FCR |= RB_FCR_RX_FIFO_CLR) /* Clear the current receive FIFO */
#define UART0_CLR_TXFIFO() (R8_UART0_FCR |= RB_FCR_TX_FIFO_CLR) /* Clear the current transmit FIFO */
#define UART0_GetITFlag() (R8_UART0_IIR & RB_IIR_INT_MASK) /* Get the current interrupt flag */
// please refer to LINE error and status define
#define UART0_GetLinSTA() (R8_UART0_LSR) /* Get the current communication status */
#define UART0_GetMSRSTA() (R8_UART0_MSR) /* Get the current flow control status, only applicable to UART0 */
#define UART0_SendByte(b) (R8_UART0_THR = b) /* Serial port single byte transmission */
void UART0_SendString( PUINT8 buf, UINT16 l ); /* Serial multi-byte transmission */
#define UART0_RecvByte() ( R8_UART0_RBR ) /* Serial port read single byte */
UINT16 UART0_RecvString( PUINT8 buf ); /* Serial port read multibyte */
/****************** UART1 */
void UART1_DefInit( void ); /* Serial port default initialization configuration */
void UART1_BaudRateCfg( UINT32 baudrate ); /* Serial port baud rate configuration */
void UART1_ByteTrigCfg( UARTByteTRIGTypeDef b ); /* Serial byte trigger interrupt configuration */
void UART1_INTCfg( UINT8 s, UINT8 i ); /* Serial port interrupt configuration */
void UART1_Reset( void ); /* Serial port software reset */
#define UART1_CLR_RXFIFO() (R8_UART1_FCR |= RB_FCR_RX_FIFO_CLR) /* Clear the current receive FIFO */
#define UART1_CLR_TXFIFO() (R8_UART1_FCR |= RB_FCR_TX_FIFO_CLR) /* Clear the current transmit FIFO */
#define UART1_GetITFlag() (R8_UART1_IIR&RB_IIR_INT_MASK) /* Get the current interrupt flag */
// please refer to LINE error and status define
#define UART1_GetLinSTA() (R8_UART1_LSR) /* Get the current communication status */
#define UART1_SendByte(b) (R8_UART1_THR = b) /* Serial port single byte transmission */
void UART1_SendString( PUINT8 buf, UINT16 l ); /* Serial multi-byte transmission */
#define UART1_RecvByte() ( R8_UART1_RBR ) /* Serial port read single byte */
UINT16 UART1_RecvString( PUINT8 buf ); /* Serial port read multibyte */
/****************** UART2 */
void UART2_DefInit( void ); /* Serial port default initialization configuration */
void UART2_BaudRateCfg( UINT32 baudrate ); /* Serial port baud rate configuration */
void UART2_ByteTrigCfg( UARTByteTRIGTypeDef b ); /* Serial byte trigger interrupt configuration */
void UART2_INTCfg( UINT8 s, UINT8 i ); /* Serial port interrupt configuration */
void UART2_Reset( void ); /* Serial port software reset */
#define UART2_CLR_RXFIFO() (R8_UART2_FCR |= RB_FCR_RX_FIFO_CLR) /* Clear the current receive FIFO */
#define UART2_CLR_TXFIFO() (R8_UART2_FCR |= RB_FCR_TX_FIFO_CLR) /* Clear the current transmit FIFO */
#define UART2_GetITFlag() (R8_UART2_IIR&RB_IIR_INT_MASK) /* Get the current interrupt flag */
// please refer to LINE error and status define
#define UART2_GetLinSTA() (R8_UART2_LSR) /* Get the current communication status */
#define UART2_SendByte(b) (R8_UART2_THR = b) /* Serial port single byte transmission */
void UART2_SendString( PUINT8 buf, UINT16 l ); /* Serial multi-byte transmission */
#define UART2_RecvByte() ( R8_UART2_RBR ) /* Serial port read single byte */
UINT16 UART2_RecvString( PUINT8 buf ); /* Serial port read multibyte */
/****************** UART3 */
void UART3_DefInit( void ); /* Serial port default initialization configuration */
void UART3_BaudRateCfg( UINT32 baudrate ); /* Serial port baud rate configuration */
void UART3_ByteTrigCfg( UARTByteTRIGTypeDef b ); /* Serial byte trigger interrupt configuration */
void UART3_INTCfg( UINT8 s, UINT8 i ); /* Serial port interrupt configuration */
void UART3_Reset( void ); /* Serial port software reset */
#define UART3_CLR_RXFIFO() (R8_UART3_FCR |= RB_FCR_RX_FIFO_CLR) /* Clear the current receive FIFO */
#define UART3_CLR_TXFIFO() (R8_UART3_FCR |= RB_FCR_TX_FIFO_CLR) /* Clear the current transmit FIFO */
#define UART3_GetITFlag() (R8_UART3_IIR&RB_IIR_INT_MASK) /* Get the current interrupt flag */
// please refer to LINE error and status define
#define UART3_GetLinSTA() (R8_UART3_LSR) /* Get the current communication status */
#define UART3_SendByte(b) (R8_UART3_THR = b) /* Serial port single byte transmission */
void UART3_SendString( PUINT8 buf, UINT16 l ); /* Serial multi-byte transmission */
#define UART3_RecvByte() ( R8_UART3_RBR ) /* Serial port read single byte */
UINT16 UART3_RecvString( PUINT8 buf ); /* Serial port read multibyte */
#ifdef __cplusplus
}
#endif
#endif // __CH56x_UART_H__

View File

@ -0,0 +1,57 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_bus8.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn BUS8_GPIO_Init
*
* @brief BUS8 GPIO initialization
*
* @return None
*/
void BUS8_GPIO_Init(void)
{
R32_PA_DIR = 0;
R32_PA_PU = 0xff;
R32_PA_SMT = 0xffffffff;
R32_PA_DIR |= bBUSRD | bBUSWR; //R/W signal GPIO
R32_PB_DIR |= 0x7fff;
R32_PB_SMT |= 0x7fff;
}
/*******************************************************************************
* @fn BUS8_Init
*
* @brief BUS8 initialization
*
* @param addroe:0x00-none;0x04-[5:0];0x08-[9:0];0x0c-[14:0];
* width: 0x00-3;0x10-5;0x20-9;0x30-16;
* hold: 0x00-2;0x40-3;
* setup: 0x00-2;0x80-3;
*
* @return None
*/
void BUS8_Init(UINT8 addroe, UINT8 width, UINT8 hold, UINT8 setup)
{
R8_XBUS_CONFIG = addroe | width | hold | setup;
R8_XBUS_CONFIG |= RB_XBUS_ENABLE; //Enable
BUS8_GPIO_Init();
}

View File

@ -0,0 +1,115 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_clk.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn SystemInit
*
* @brief System clock initialization
*
* @param systemclck: system clock Hz
*
* @return None
*/
void SystemInit(uint32_t systemclck)
{
uint8_t sc;
sc = systemclck/1000000;
switch( sc )
{
case CLK_SOURCE_PLL_15MHz:
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_PLL_DIV = 0x40 | 0x02;
R8_CLK_CFG_CTRL = 0x80 ;
break;
case CLK_SOURCE_PLL_30MHz:
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_PLL_DIV = 0x40;
R8_CLK_CFG_CTRL = 0x80 | RB_CLK_SEL_PLL;
break;
case CLK_SOURCE_PLL_60MHz:
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_PLL_DIV = 0x40 | 0x08;
R8_CLK_CFG_CTRL = 0x80 | RB_CLK_SEL_PLL;
break;
case CLK_SOURCE_PLL_80MHz:
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_PLL_DIV = 0x40 | 0x06;
R8_CLK_CFG_CTRL = 0x80 | RB_CLK_SEL_PLL;
break;
case CLK_SOURCE_PLL_96MHz:
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_PLL_DIV = 0x40 | 0x05;
R8_CLK_CFG_CTRL = 0x80 | RB_CLK_SEL_PLL;
break;
case CLK_SOURCE_PLL_120MHz:
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_PLL_DIV = 0x40 | 0x04;
R8_CLK_CFG_CTRL = 0x80 | RB_CLK_SEL_PLL;
break;
default :
break;
}
R8_SAFE_ACCESS_SIG = 0;
}
/*******************************************************************************
* @fn GetSysClock
*
* @brief Get the current system clock
*
* @param None
*
* @return Hz
*/
UINT32 GetSysClock( void )
{
UINT8 rev;
rev = R8_CLK_PLL_DIV & 0x0F;
if(R8_CLK_CFG_CTRL & RB_CLK_SEL_PLL){ //The system clock source comes from the 480M provided by the USB PHY
if(rev == 0){
return (30000000);
}
else{
return (480000000/R8_CLK_PLL_DIV);
}
}
else{ //The system clock source comes from an external crystal oscillator 30M
if(rev == 0){
return (2000000);
}
else{
return (30000000/R8_CLK_PLL_DIV);
}
}
}

View File

@ -0,0 +1,132 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_dvp.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn DVP_INTCfg
*
* @brief DVP interrupt configuration
*
* @param s: interrupt control status
ENABLE - Enables the corresponding interrupt
DISABLE - disables the corresponding interrupt
i: interrupt type
RB_DVP_IE_STP_FRM - end of frame interrupt
RB_DVP_IE_FIFO_OV - Receive FIFO overflow interrupt
RB_DVP_IE_FRM_DONE - end of frame interrupt
RB_DVP_IE_ROW_DONE - end of line break
RB_DVP_IE_STR_FRM - start of frame interrupt
*
* @return None
**/
void DVP_INTCfg( UINT8 s, UINT8 i )
{
if(s){
R8_DVP_INT_EN |= i;
}
else{
R8_DVP_INT_EN &= ~i;
}
}
/*******************************************************************************
* @fn DVP_Mode
*
* @brief DVP mode
*
* @param s: data width
RB_DVP_D8_MOD - 8-bit mode
RB_DVP_D10_MOD - 10-bit mode
RB_DVP_D12_MOD - 12-bit mode
i: Compressed Data Mode
Video_Mode - enable video mode
JPEG_Mode - Enable JPEG mode
*
* @return None
*/
void DVP_Mode( UINT8 s, DVP_Data_ModeTypeDef i)
{
R8_DVP_CR0 &= ~RB_DVP_MSK_DAT_MOD; //Restore default mode 8bit mode
if(s){
R8_DVP_CR0 |= s;
}
else{
R8_DVP_CR0 &= ~(3<<4);
}
if(i){
R8_DVP_CR0 |= RB_DVP_JPEG;
}
else{
R8_DVP_CR0 &= ~RB_DVP_JPEG;
}
}
/*******************************************************************************
* @fn DVP_Cfg
*
* @brief DVP configuration
*
* @param s: DMA enable control
DVP_DMA_Enable - DMA enable
DVP_DMA_Disable - DMA disable
i: Flag and FIFO Clear Control
DVP_FLAG_FIFO_RESET_Enable - Reset flag and FIFO
DVP_FLAG_FIFO_RESET_Disable - cancel reset operation
j: Receive Logic Reset Control
DVP_RX_RESET_Enable - reset receiver logic
DVP_RX_RESET_Disable - cancel reset operation
*
* @return None
*/
void DVP_Cfg( DVP_DMATypeDef s, DVP_FLAG_FIFO_RESETTypeDef i, DVP_RX_RESETTypeDef j)
{
switch( s )
{
case DVP_DMA_Enable:
R8_DVP_CR1 |= RB_DVP_DMA_EN;
break;
case DVP_DMA_Disable:
R8_DVP_CR1 &= ~RB_DVP_DMA_EN;
break;
default:
break;
}
switch( i )
{
case DVP_RX_RESET_Enable:
R8_DVP_CR1 |= RB_DVP_ALL_CLR;
break;
case DVP_RX_RESET_Disable:
R8_DVP_CR1 &= ~RB_DVP_ALL_CLR;
break;
default:
break;
}
switch( j )
{
case DVP_RX_RESET_Enable:
R8_DVP_CR1 |= RB_DVP_RCV_CLR;
break;
case DVP_RX_RESET_Disable:
R8_DVP_CR1 &= ~RB_DVP_RCV_CLR;
break;
default:
break;
}
}

View File

@ -0,0 +1,182 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_ecdc.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn ECDC_Init
*
* @brief initialization
*
* @param ecdcmode - 0-SM4&ECB 1-AES&ECB 2-SM4&CTR 3-AES&CTR
* clkmode - 1-closure 2-240M 3-160M
* keylen - 0-128bit 1-192bit 2-256bit
* pkey - key value pointer
* pcount - counter value pointer
*
* @return None
*/
void ECDC_Init( UINT8 ecdcmode, UINT8 clkmode, UINT8 keylen, PUINT32 pkey, PUINT32 pcount )
{
R8_ECDC_INT_FG |= 0xFF;
R16_ECEC_CTRL = 0;
R16_ECEC_CTRL |= (ecdcmode&0x03)<<8; //Working mode selection
R16_ECEC_CTRL |= (keylen&0x03)<<10; //key length setting
R16_ECEC_CTRL |= (clkmode&0x03)<<4; //Encryption and decryption clock frequency division factor, aes encryption and decryption works at 240Mhz
ECDC_SetKey(pkey, keylen);
if(R16_ECEC_CTRL & RB_ECDC_CIPHER_MOD) //Execute only in CTR mode, the only difference between CTR and ECB mode programming
ECDC_SetCount(pcount);
R8_ECDC_INT_FG |= RB_ECDC_IF_EKDONE;
R16_ECEC_CTRL |= RB_ECDC_KEYEX_EN;
R16_ECEC_CTRL &= ~RB_ECDC_KEYEX_EN;
while(!(R8_ECDC_INT_FG & RB_ECDC_IF_EKDONE));
R8_ECDC_INT_FG |= RB_ECDC_IF_EKDONE;
}
/*******************************************************************************
* @fn ECDC_SetKey
*
* @brief set key
*
* @param pkey - key value pointer
* keylen - 0-128bit 1-192bit 2-256bit
* @return None
*/
void ECDC_SetKey( PUINT32 pkey, UINT8 keylen )
{
keylen = keylen&0x03;
R32_ECDC_KEY_31T0 = *pkey++;
R32_ECDC_KEY_63T32 = *pkey++;
R32_ECDC_KEY_95T64 = *pkey++;
R32_ECDC_KEY_127T96 = *pkey++;
if(keylen){
R32_ECDC_KEY_159T128 = *pkey++;
R32_ECDC_KEY_191T160 = *pkey++;
}
if(keylen>1){
R32_ECDC_KEY_223T192 = *pkey++;
R32_ECDC_KEY_255T224 = *pkey++;
}
}
/*******************************************************************************
* @fn ECDC_SetCount
*
* @brief set counter
*
* @param pcount - counter value pointer
*
* @return None
*/
void ECDC_SetCount( PUINT32 pcount )
{
R32_ECDC_IV_31T0 = *pcount++;
R32_ECDC_IV_63T32 = *pcount++;
R32_ECDC_IV_95T64 = *pcount++;
R32_ECDC_IV_127T96 = *pcount++;
}
/*******************************************************************************
* @fn ECDC_Excute
*
* @brief Set direction and mode
*
* @param excutemode - RAMX encryption -0x84
* RAMX decryption -0x8c
* 128bits data single encryption -0x02
* 128bits data single decryption -0x0a
* Peripheral to RAMX encryption -0x02
* Peripheral to RAMX decryption -0x0a
* RAMX to Peripheral encryption -0x04
* RAMX to Peripheral decryption -0x0c
* endianmode - big_endian-1 little_endian-0
*
* @return None
*/
void ECDC_Excute( UINT8 excutemode, UINT8 endianmode )
{
R16_ECEC_CTRL &= 0xDF71;
R16_ECEC_CTRL |= excutemode;
if(endianmode)
R16_ECEC_CTRL |= RB_ECDC_DAT_MOD;
else
R16_ECEC_CTRL &= ~RB_ECDC_DAT_MOD;
}
/*******************************************************************************
* @fn ECDC_SingleRegister
*
* @brief Single register encryption and decryption
*
* @param pWdatbuff - Write data first address
* pRdatbuff - Read data first address
*
* @return None
*/
void ECDC_SingleRegister( PUINT32 pWdatbuff, PUINT32 pRdatbuff )
{
R32_ECDC_SGSD_127T96 = pWdatbuff[3]; //low address
R32_ECDC_SGSD_95T64 = pWdatbuff[2];
R32_ECDC_SGSD_63T32 = pWdatbuff[1];
R32_ECDC_SGSD_31T0 = pWdatbuff[0]; //high address
while(!(R8_ECDC_INT_FG & RB_ECDC_IF_SINGLE));
R8_ECDC_INT_FG |= RB_ECDC_IF_SINGLE;
pRdatbuff[3] = R32_ECDC_SGRT_127T96;
pRdatbuff[2] = R32_ECDC_SGRT_95T64;
pRdatbuff[1] = R32_ECDC_SGRT_63T32;
pRdatbuff[0] = R32_ECDC_SGRT_31T0;
}
/*******************************************************************************
* @fn ECDC_RAMX
*
* @brief RAMX encryption and decryption
*
* @param ram_add - first address
* ram_len - length
* @return None
**/
void ECDC_SelfDMA( UINT32 ram_addr, UINT32 ram_len )
{
R32_ECDC_SRAM_ADDR = ram_addr;
R32_ECDC_SRAM_LEN = ram_len; //start converting
while(!(R8_ECDC_INT_FG & RB_ECDC_IF_WRSRAM)); //Completion flag
R8_ECDC_INT_FG |= RB_ECDC_IF_WRSRAM;
}
/*******************************************************************************
* @fn ECDC_RloadCount
*
* @brief In CTR mode, every time a block is encrypted/decrypted, the counter value is reloaded
*
* @param pcount - counter value pointer
*
* @return None
*/
void ECDC_RloadCount( UINT8 excutemode, UINT8 endianmode, PUINT32 pcount )
{
R16_ECEC_CTRL &= 0xDFF9; //second position third position 0
ECDC_SetCount(pcount);
ECDC_Excute(excutemode, endianmode);
}

View File

@ -0,0 +1,870 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_emmc.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn EMMCIO0Init
*
* @brief EMMC Controller Initializtion
*
* @return OP_SUCCESS
*/
UINT8 EMMCIO0Init( void )
{
/* GPIO configuration */
R32_PB_DRV |= bSDCMD; //Command Line
R32_PB_PU |= bSDCMD;
R32_PB_DIR |= bSDCK; //CLK Line
R32_PB_DRV |= bSDCK;
R32_PB_PU |= (0x1f<<17); //Data Line
R32_PA_PU |= (7<<0);
R32_PA_DRV |= (7<<0); // Drive Capacity
R32_PB_DRV |= (0x1f<<17); // Drive Capacity
/* Controller Register */
R8_EMMC_CONTROL = RB_EMMC_ALL_CLR | RB_EMMC_RST_LGC ; // reset all register
R8_EMMC_CONTROL = RB_EMMC_NEGSMP | RB_EMMC_DMAEN ; // Enable EMMCcard
R32_PB_DIR |= bSDCK;
R16_EMMC_CLK_DIV = RB_EMMC_CLKOE | LOWEMMCCLK|RB_EMMC_PHASEINV;
/* Enable Interruption */
R16_EMMC_INT_FG = 0xffff;
R16_EMMC_INT_EN = RB_EMMC_IE_FIFO_OV | //Enable error Interruption
RB_EMMC_IE_TRANERR |
RB_EMMC_IE_DATTMO |
RB_EMMC_IE_REIDX_ER |
RB_EMMC_IE_RECRC_WR |
RB_EMMC_IE_RE_TMOUT;
/* Overtime */
R8_EMMC_TIMEOUT = 35; // calculating overtime
return OP_SUCCESS;
}
/*******************************************************************************
* @fn CheckCMDComp
*
* @brief Estimate the end of Command
*
* @param pEMMCPara
*
* @return CMD_NULL
**/
UINT8 CheckCMDComp( PSD_PARAMETER pEMMCPara )
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_CMDDONE)
{
R16_EMMC_INT_FG = RB_EMMC_IF_CMDDONE;
return CMD_SUCCESS;
}
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
return CMD_NULL;
}
/*******************************************************************************
* @fn EMMCResetIdle
*
* @brief when EMMC waiting status,do the OCR analysis
*
* @param pEMMCPara
*
* @return None
*/
void EMMCResetIdle( PSD_PARAMETER pEMMCPara )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
cmd_arg_val = 0x0;
cmd_set_val = 0x0|EMMC_CMD0;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while( CheckCMDComp( pEMMCPara ) == CMD_NULL );
}
/*******************************************************************************
* @fn EMMCReadOCR
*
* @brief when EMMC waiting status,do the OCR analysis
*
* @param pEMMCPara
*
* @return CMD_SUCCESS
*/
UINT8 EMMCReadOCR( PSD_PARAMETER pEMMCPara )
{
UINT8 i;
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta = 0;
UINT32 cmd_rsp_val; //command returned value
for(i=0; i<100; i++)
{
cmd_arg_val = 0x40FF0080; //request switching voltage
// cmd_arg_val = 0x40000800; //request switching voltage
cmd_set_val = 0 | //ACK's index
0 | //CRC
RESP_TYPE_48 | //ACK type
EMMC_CMD1; //command's index this moment
mDelaymS(10);
EMMCSendCmd(cmd_arg_val, cmd_set_val);
mDelayuS(2);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta!= CMD_NULL )
{
break;
}
}
if(sta == CMD_SUCCESS)
{
cmd_rsp_val = R32_EMMC_RESPONSE3;
if(cmd_rsp_val & (1<<31))
{
break;
}
}
mDelaymS(50);
}
if(i == 100) return OP_FAILED;
return sta;
}
/*******************************************************************************
* @fn EMMCReadCID
*
* @brief acquire 128bit CID parameter
*
* @param pEMMCPara
*
* @return OP_SUCCESS
**/
UINT8 EMMCReadCID( PSD_PARAMETER pEMMCPara )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
cmd_arg_val = 0;
cmd_set_val = 0 |
0 |
RESP_TYPE_136 |
EMMC_CMD2;
EMMCSendCmd( cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
if(sta == CMD_SUCCESS)
{
pEMMCPara->EMMC_CID[0] = R32_EMMC_RESPONSE0;
pEMMCPara->EMMC_CID[1] = R32_EMMC_RESPONSE1;
pEMMCPara->EMMC_CID[2] = R32_EMMC_RESPONSE2;
pEMMCPara->EMMC_CID[3] = R32_EMMC_RESPONSE3;
}
return sta;
}
/*******************************************************************************
* @fn EMMCSetRCA
*
* @brief assign relative address to deviceARC 16bit
*
* @param pEMMCPara
*
* @return OP_SUCCESS
*/
UINT8 EMMCSetRCA( PSD_PARAMETER pEMMCPara )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
cmd_arg_val = 0xAAAA0000;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD3;
mDelaymS(10);
EMMCSendCmd(cmd_arg_val,cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
if(sta == CMD_SUCCESS)
{
pEMMCPara->EMMC_RCA = 0xAAAA;
}
return sta;
}
/*******************************************************************************
* @fn EMMCReadCSD
*
* @brief acquire 128bit CSD parameter and get it analyzed
*
* @param pEMMCPara
*
* @return OP_SUCCESS
*/
UINT8 EMMCReadCSD( PSD_PARAMETER pEMMCPara )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
UINT32 disk_block_num = 0;
cmd_arg_val = pEMMCPara->EMMC_RCA<<16;
cmd_set_val = 0 |
0 |
RESP_TYPE_136 |
EMMC_CMD9;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
if(sta == CMD_SUCCESS)
{
pEMMCPara->EMMC_CSD[0] = R32_EMMC_RESPONSE0;
pEMMCPara->EMMC_CSD[1] = R32_EMMC_RESPONSE1;
pEMMCPara->EMMC_CSD[2] = R32_EMMC_RESPONSE2;
pEMMCPara->EMMC_CSD[3] = R32_EMMC_RESPONSE3;
disk_block_num = (((pEMMCPara->EMMC_CSD[2]&0x3ff)<<2) | ((pEMMCPara->EMMC_CSD[1])>>30));
if(disk_block_num == 0xFFF)
{
pEMMCPara->EMMCSecNum = 0xFFF;
}
else
{
pEMMCPara->EMMCType = EMMCIO_CAPACITY_SD_CARD_V2_0;
/* memory capacity = BLOCKNR*BLOCK_LEN = (C_SIZE+1)<<(C_SIZE_MULT+2)<<(READ_BL_LEN) */
disk_block_num = ( (((pEMMCPara->EMMC_CSD[2]&0x3ff)<<2) | (pEMMCPara->EMMC_CSD[1]>>30)) + 1 );
disk_block_num = ( (disk_block_num) << (((pEMMCPara->EMMC_CSD[1]>>15)&0x07) + 2));
}
}
pEMMCPara->EMMCSecSize = 1<<((pEMMCPara->EMMC_CSD[2]>>16)&0x000f);
return sta;
}
/*******************************************************************************
* @fn SelectEMMCCard
*
* @brief select card
*
* @param pEMMCPara
*
* @return OP_SUCCESS
*/
UINT8 SelectEMMCCard(PSD_PARAMETER pEMMCPara)
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
cmd_arg_val = pEMMCPara->EMMC_RCA<<16;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD7;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
return sta;
}
UINT8 ReadEMMCStatus(PSD_PARAMETER pEMMCPara)
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
cmd_arg_val = pEMMCPara->EMMC_RCA<<16;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD13;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
return sta;
}
/*******************************************************************************
* @fn SwitchEMMCIOBusType
*
* @brief set the IO bus_mode
*
* @param pEMMCPara -
* bus_mode -
*
* @return OP_SUCCESS
*/
UINT8 EMMCSetBusWidth(PSD_PARAMETER pEMMCPara, UINT8 bus_mode)
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
if(bus_mode == 0) cmd_arg_val = 0x03B70100;
else cmd_arg_val = 0x03B70200;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD6;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
return sta;
}
UINT8 EMMCSetHighSpeed(PSD_PARAMETER pEMMCPara)
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
cmd_arg_val = 0x03B90100;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_R1b |
EMMC_CMD6;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
return sta;
}
/*******************************************************************************
* @fn ConfigAllSD
*
* @brief EMMC Information
*
* @param pEMMCPara
*
* @return OP_SUCCESS
**/
#define SD2CMD EMMCSendCmd
__attribute__ ((aligned(8))) UINT8 buf[512] __attribute__((section(".DMADATA")));
UINT8 EMMCCardConfig( PSD_PARAMETER pEMMCPara )
{
UINT8 sta;
//cmd0
EMMCResetIdle( pEMMCPara );
mDelaymS(30);
sta = EMMCReadOCR( pEMMCPara );
if(sta!=CMD_SUCCESS) return OP_FAILED;
//cmd2
sta = EMMCReadCID( pEMMCPara );
if(sta!=CMD_SUCCESS) return OP_FAILED;
//cmd3
mDelaymS(30);
sta = EMMCSetRCA( pEMMCPara );
if(sta!=CMD_SUCCESS) return OP_FAILED;
//cmd9
sta = EMMCReadCSD( pEMMCPara );
if(sta!=CMD_SUCCESS) return OP_FAILED;
//cmd7;
mDelaymS(30);
sta = SelectEMMCCard( pEMMCPara );
if(sta!=CMD_SUCCESS) return OP_FAILED;
mDelaymS(30);
if(pEMMCPara->EMMCSecNum == 0xFFF)
{
sta = EMMCCardReadEXCSD( pEMMCPara, buf );
if(sta!=OP_SUCCESS) return OP_FAILED;
pEMMCPara->EMMCSecNum = *((PUINT32)&buf[212]); // SEC_COUNT [215:212] MSB-LSB
}
//cmd6
sta = EMMCSetBusWidth(pEMMCPara, 1);
if(sta!=CMD_SUCCESS) return OP_FAILED;
R8_EMMC_CONTROL = (R8_EMMC_CONTROL&~RB_EMMC_LW_MASK) | bLW_OP_DAT8; // 8line_mode
mDelaymS(30);
//configure high clock rate
EMMCSetHighSpeed(pEMMCPara);
//cmd13
mDelaymS(30);
sta = ReadEMMCStatus( pEMMCPara );
if(sta!=CMD_SUCCESS) return OP_FAILED;
mDelaymS(30);
// R8_EMMC_CONTROL |= RB_EMMC_NEGSMP;
R16_EMMC_CLK_DIV = RB_EMMC_CLKMode|
RB_EMMC_PHASEINV|
RB_EMMC_CLKOE |
8;
return OP_SUCCESS;
}
UINT8 EMMCCardConfig_N( PSD_PARAMETER pEMMCPara )
{
UINT8 sta;
EMMCResetIdle( pEMMCPara );
mDelaymS(30);
sta = EMMCReadOCR( pEMMCPara );
if(sta!=CMD_SUCCESS)
{
return OP_FAILED;
}
sta = EMMCReadCID( pEMMCPara );
if(sta!=CMD_SUCCESS)
{
return OP_FAILED;
}
mDelaymS(30);
sta = EMMCSetRCA( pEMMCPara );
if(sta!=CMD_SUCCESS)
{
return OP_FAILED;
}
sta = EMMCReadCSD( pEMMCPara );
if(sta!=CMD_SUCCESS)
{
return OP_FAILED;
}
mDelaymS(30);
sta = SelectEMMCCard( pEMMCPara );
if(sta!=CMD_SUCCESS)
{
return OP_FAILED;
}
R16_EMMC_CLK_DIV = RB_EMMC_CLKMode|
RB_EMMC_CLKOE |
LOWEMMCCLK;
sta = ReadEMMCStatus( pEMMCPara );
if(sta!=CMD_SUCCESS)
{
return OP_FAILED;
}
if(pEMMCPara->EMMCSecNum == 0xFFF)
{
sta = EMMCCardReadEXCSD( pEMMCPara, buf );
if(sta!=OP_SUCCESS) return OP_FAILED;
pEMMCPara->EMMCSecNum = *((PUINT32)&buf[212]); // SEC_COUNT [215:212] MSB-LSB
}
sta = EMMCSetBusWidth(pEMMCPara, 1);
if(sta!=CMD_SUCCESS) return OP_FAILED;
R8_EMMC_CONTROL = (R8_EMMC_CONTROL&~RB_EMMC_LW_MASK) | bLW_OP_DAT8; // 8line_mode
//switching frequency
while(!(R32_EMMC_STATUS & (1<<17)));
sta = EMMCSetHighSpeed(pEMMCPara);
if(sta!=CMD_SUCCESS) return OP_FAILED;
while(!(R32_EMMC_STATUS & (1<<17)));
//configure higher clock rate
R16_EMMC_CLK_DIV = RB_EMMC_CLKMode|
RB_EMMC_CLKOE |
4|RB_EMMC_PHASEINV;
return OP_SUCCESS;
}
/*******************************************************************************
* @fn EMMCIOTransErrorDeal
*
* @brief error processing
*
* @return OP_SUCCESS
*******************************************************************************/
UINT8 EMMCIOTransErrorDeal( PSD_PARAMETER pEMMCPara )
{
pEMMCPara->EMMCOpErr = R16_EMMC_INT_FG;
R16_EMMC_INT_FG = 0xffff;
return OP_SUCCESS;
}
/*******************************************************************************
* @fn EMMCCardReadEXCSD
*
* @brief read single section
*
* @param pEMMCPara
* Lbaaddr - section first address
*
* @return OP_SUCCESS
**/
UINT8 EMMCCardReadEXCSD( PSD_PARAMETER pEMMCPara, PUINT8 pRdatbuf )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
R32_EMMC_DMA_BEG1 = (UINT32)pRdatbuf;
R32_EMMC_TRAN_MODE = 0;
R32_EMMC_BLOCK_CFG = 512<<16 | 1;
cmd_arg_val = 0;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD8;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_TRANDONE) break;
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
}
R16_EMMC_INT_FG = 0xffff;
return OP_SUCCESS;
}
/*******************************************************************************
* @fn EMMCCardReadOneSec
*
* @brief read single section
*
* @param pEMMCPara
* pRdatbuf -- read buffer address
* Lbaaddr
*
* @return OP_SUCCESS
**/
UINT8 EMMCCardReadOneSec( PSD_PARAMETER pEMMCPara, PUINT8 pRdatbuf, UINT32 Lbaaddr )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
if(Lbaaddr > (pEMMCPara->EMMCSecNum)) return OP_INVALID_ADD;
R32_EMMC_DMA_BEG1 = (UINT32)pRdatbuf;
R32_EMMC_TRAN_MODE = 0;
R32_EMMC_BLOCK_CFG = (pEMMCPara->EMMCSecSize)<<16 | 1;
cmd_arg_val = Lbaaddr;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD17;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_TRANDONE) break;
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
}
R16_EMMC_INT_FG = 0xffff;
return OP_SUCCESS;
}
/*******************************************************************************
* @fn EMMCCardReadMulSec
*
* @brief read continuous multiple sections
*
* @param pEMMCPara -
* pReqnum - request continuous sections address
* pRdatbuf -
* Lbaaddr -
*
* @return OP_SUCCESS
*/
UINT8 EMMCCardReadMulSec( PSD_PARAMETER pEMMCPara, PUINT16 pReqnum, PUINT8 pRdatbuf, UINT32 Lbaaddr )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
if(Lbaaddr > (pEMMCPara->EMMCSecNum)) return OP_INVALID_ADD;
R32_EMMC_DMA_BEG1 = (UINT32)pRdatbuf; //data buffer address
R32_EMMC_TRAN_MODE = 0; //EMMC to controller
R32_EMMC_BLOCK_CFG = (pEMMCPara->EMMCSecSize)<<16 | (*pReqnum);
//cmd18
cmd_arg_val = Lbaaddr;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD18;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_TRANDONE)
{
R16_EMMC_INT_FG = RB_EMMC_IF_CMDDONE;
//cmd12
cmd_arg_val = 0;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_R1b |
EMMC_CMD12;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
break;
}
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
}
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
R16_EMMC_INT_FG = 0xffff;
*pReqnum = (UINT16)R32_EMMC_STATUS; // successfully transferred sections
return sta;
}
/*******************************************************************************
* @fn EMMCCardWriteMulSec
* @brief write continuous multiple sections
* @param pSDPara -
* pReqnum -
* pWdatbuf -
* Lbaaddr -
* @return OP_SUCCESS
**/
UINT8 EMMCCardWriteMulSec( PSD_PARAMETER pEMMCPara, PUINT16 pReqnum, PUINT8 pWdatbuf, UINT32 Lbaaddr )
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
if(Lbaaddr > (pEMMCPara->EMMCSecNum)) return OP_INVALID_ADD;
//cmd25
cmd_arg_val = Lbaaddr;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD25;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
if( sta == CMD_FAILED ) return OP_FAILED;
//DAT
R32_EMMC_TRAN_MODE = RB_EMMC_DMA_DIR;
R32_EMMC_DMA_BEG1 = (UINT32)pWdatbuf;
R32_EMMC_BLOCK_CFG = (pEMMCPara->EMMCSecSize)<<16 | (*pReqnum);
while(1)
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_BKGAP)
{
R32_EMMC_RESPONSE3 = 0;
R16_EMMC_INT_FG = RB_EMMC_IF_BKGAP;
}
else if(R16_EMMC_INT_FG & RB_EMMC_IF_TRANDONE)
{
R16_EMMC_INT_FG = RB_EMMC_IF_CMDDONE;
//cmd12
cmd_arg_val = 0;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_R1b |
EMMC_CMD12;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
break;
}
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
}
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
R16_EMMC_INT_FG = 0xffff;
*pReqnum = (UINT16)R32_EMMC_STATUS;
return sta;
}
/*******************************************************************************
* @fn AES_EMMCWriteMulSec
*
* @brief Write continuous multiple sections
*
* @param pEMMCPara - SD information structure pointer
* pReqnum - Request to the sector number variable address consecutively
* pWdatbuf - Write to the data cache address
* Lbaaddr - Write the sector head address continuously
*
* @return None
***/
UINT8 AES_EMMCWriteMulSec( PSD_PARAMETER pEMMCPara, PUINT32 pReqnum, PUINT32 pWdatbuf, UINT32 Lbaaddr, UINT8 excutemode, UINT8 endianmode, PUINT32 pcount)
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
UINT8 sta;
if(Lbaaddr > (pEMMCPara->EMMCSecNum)) return OP_INVALID_ADD;
//cmd25
cmd_arg_val = Lbaaddr;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD25;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
if( sta == CMD_FAILED ) return OP_FAILED;
//DAT
ECDC_Excute(excutemode, endianmode);
R32_EMMC_TRAN_MODE |= RB_EMMC_DMA_DIR;
R32_EMMC_DMA_BEG1 = (UINT32)pWdatbuf;
R32_EMMC_BLOCK_CFG = (pEMMCPara->EMMCSecSize)<<16 | (*pReqnum);
while(1)
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_BKGAP)
{
///////////////////////////////////////////////CTR mode
if(R16_ECEC_CTRL & RB_ECDC_CIPHER_MOD)
ECDC_RloadCount( excutemode, endianmode, pcount );
R32_EMMC_RESPONSE3 = 0; //start transform
R16_EMMC_INT_FG |= RB_EMMC_IF_BKGAP;
}
else if(R16_EMMC_INT_FG & RB_EMMC_IF_TRANDONE)
{
R16_EMMC_INT_FG = RB_EMMC_IF_CMDDONE;
//cmd12
cmd_arg_val = 0;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_R1b |
EMMC_CMD12;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
break;
}
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
}
while(1)
{
sta = CheckCMDComp( pEMMCPara );
if( sta != CMD_NULL ) break;
}
R16_EMMC_INT_FG = 0xffff;
*pReqnum = (UINT16)R32_EMMC_STATUS; //the number of blocks transferred successfully
return sta;
}
/*******************************************************************************
* @fn AES_EMMCReadMulSec
*
* @brief Read continuous multiple sections
*
* @param pEMMCPara - SD information structure pointer
* pReqnum - Request to the sector number variable address consecutively
* pWdatbuf - Write to the data cache address
* Lbaaddr - Write the sector head address continuously
*
* @return OP_SUCCESS - suc
* other - err
**/
UINT8 AES_EMMCReadMulSec( PSD_PARAMETER pEMMCPara, PUINT32 pReqnum, PUINT32 pRdatbuf, UINT32 Lbaaddr, UINT8 excutemode, UINT8 endianmode, PUINT32 pcount)
{
UINT32 cmd_arg_val;
UINT16 cmd_set_val;
if(Lbaaddr > (pEMMCPara->EMMCSecNum)) return OP_INVALID_ADD;
//CTR mode.Once the transmission is completed ,turn off the clock.
if(R16_ECEC_CTRL & RB_ECDC_CIPHER_MOD)
{
R16_ECEC_CTRL &= 0xFFF9; //bit2 and bit3 set 0
ECDC_SetCount(pcount);
R32_EMMC_TRAN_MODE |= RB_EMMC_AUTOGAPSTOP | RB_EMMC_GAP_STOP;
}
ECDC_Excute(excutemode, endianmode);
R32_EMMC_DMA_BEG1 = (UINT32)pRdatbuf;
R32_EMMC_TRAN_MODE &= ~RB_EMMC_DMA_DIR;
R32_EMMC_BLOCK_CFG = (pEMMCPara->EMMCSecSize)<<16 | (*pReqnum);
//cmd18
cmd_arg_val = Lbaaddr;
cmd_set_val = RB_EMMC_CKIDX |
RB_EMMC_CKCRC |
RESP_TYPE_48 |
EMMC_CMD18;
EMMCSendCmd(cmd_arg_val, cmd_set_val);
while(1)
{
if(R16_ECEC_CTRL & RB_ECDC_CIPHER_MOD)
{
if(R16_EMMC_INT_FG & RB_EMMC_IF_BKGAP)
{
/* CTR mode */
if(R16_ECEC_CTRL & RB_ECDC_CIPHER_MOD)
ECDC_RloadCount( excutemode, endianmode, pcount );
R32_EMMC_TRAN_MODE &= ~RB_EMMC_GAP_STOP;
R16_EMMC_INT_FG |= RB_EMMC_IF_BKGAP;
}
}
if(R16_EMMC_INT_FG & RB_EMMC_IF_TRANDONE) break;
if( pEMMCPara->EMMCOpErr ) return CMD_FAILED;
}
R16_EMMC_INT_FG = 0xffff;
*pReqnum = (UINT16)R32_EMMC_STATUS; //the number of blocks transferred successfully
return OP_SUCCESS;
}

View File

@ -0,0 +1,315 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_eth.c
* Author : WCH
* Version : V1.0
* Date : 2023/03/03
* Description : This file provides all the ETH firmware functions.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
ETH_DMADESCTypeDef *DMATxDescToSet;
ETH_DMADESCTypeDef *DMARxDescToGet;
/*********************************************************************
* @fn ETH_StructInit
*
* @brief Fills each ETH_InitStruct member with its default value.
*
* @param ETH_InitStruct - pointer to a ETH_InitTypeDef structure
* which will be initialized.
*
* @return none
*/
void ETH_StructInit(ETH_InitTypeDef *ETH_InitStruct)
{
/*------------------------ MAC -----------------------------------*/
ETH_InitStruct->ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
ETH_InitStruct->ETH_Watchdog = ETH_Watchdog_Enable;
ETH_InitStruct->ETH_Jabber = ETH_Jabber_Enable;
ETH_InitStruct->ETH_InterFrameGap = ETH_InterFrameGap_96Bit;
ETH_InitStruct->ETH_CarrierSense = ETH_CarrierSense_Enable;
ETH_InitStruct->ETH_Speed = ETH_Speed_10M;
ETH_InitStruct->ETH_ReceiveOwn = ETH_ReceiveOwn_Enable;
ETH_InitStruct->ETH_LoopbackMode = ETH_LoopbackMode_Disable;
ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex;
ETH_InitStruct->ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;
ETH_InitStruct->ETH_RetryTransmission = ETH_RetryTransmission_Enable;
ETH_InitStruct->ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
ETH_InitStruct->ETH_BackOffLimit = ETH_BackOffLimit_10;
ETH_InitStruct->ETH_DeferralCheck = ETH_DeferralCheck_Disable;
ETH_InitStruct->ETH_ReceiveAll = ETH_ReceiveAll_Disable;
ETH_InitStruct->ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable;
ETH_InitStruct->ETH_PassControlFrames = ETH_PassControlFrames_BlockAll;
ETH_InitStruct->ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable;
ETH_InitStruct->ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal;
ETH_InitStruct->ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
ETH_InitStruct->ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
ETH_InitStruct->ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
ETH_InitStruct->ETH_HashTableHigh = 0x0;
ETH_InitStruct->ETH_HashTableLow = 0x0;
ETH_InitStruct->ETH_PauseTime = 0x0;
ETH_InitStruct->ETH_ZeroQuantaPause = ETH_ZeroQuantaPause_Disable;
ETH_InitStruct->ETH_PauseLowThreshold = ETH_PauseLowThreshold_Minus4;
ETH_InitStruct->ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable;
ETH_InitStruct->ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable;
ETH_InitStruct->ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable;
ETH_InitStruct->ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit;
ETH_InitStruct->ETH_VLANTagIdentifier = 0x0;
/*------------------------ DMA -----------------------------------*/
ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Disable;
ETH_InitStruct->ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
ETH_InitStruct->ETH_FlushReceivedFrame = ETH_FlushReceivedFrame_Enable;
ETH_InitStruct->ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
ETH_InitStruct->ETH_TransmitThresholdControl = ETH_TransmitThresholdControl_64Bytes;
ETH_InitStruct->ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
ETH_InitStruct->ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
ETH_InitStruct->ETH_ReceiveThresholdControl = ETH_ReceiveThresholdControl_64Bytes;
ETH_InitStruct->ETH_SecondFrameOperate = ETH_SecondFrameOperate_Disable;
ETH_InitStruct->ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
ETH_InitStruct->ETH_FixedBurst = ETH_FixedBurst_Disable;
ETH_InitStruct->ETH_RxDMABurstLength = ETH_RxDMABurstLength_1Beat;
ETH_InitStruct->ETH_TxDMABurstLength = ETH_TxDMABurstLength_1Beat;
ETH_InitStruct->ETH_DescriptorSkipLength = 0x0;
ETH_InitStruct->ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_1_1;
}
/*******************************************************************************
* @fn ETH_SoftwareReset
*
* @brief ETH software reset
*
* @return None
*/
void ETH_SoftwareReset(void)
{
/* Set the SWR bit: resets all MAC subsystem internal registers and logic */
/* After reset all the registers holds their respective reset values */
ETH->DMABMR |= ETH_DMABMR_SR;
}
/*******************************************************************************
* @fn RGMII_TXC_Delay
*
* @brief ETH send clock polarity and timing adjustment
*
* @param clock_polarity - send clock polarity
* delay_time - delay time(unit - half nanosecond)
*
* @return None
*/
void RGMII_TXC_Delay(uint8_t clock_polarity,uint8_t delay_time)
{
if(clock_polarity)
ETH->MACCR |= (uint32_t)(1<<1);
else
ETH->MACCR &= ~(uint32_t)(1<<1);
if(delay_time <= 7)
ETH->MACCR |= (uint32_t)(delay_time<<29);
else
printf("Error:delay_time is out of range!\n");
}
/*******************************************************************************
* @fn ETH_ReadPHYRegister
*
* @brief Read PHY register
*
* @param PHYAddress - PHY address
* PHYReg - PHY register address
*
* @return Value of PHY register
*/
uint16_t ETH_ReadPHYRegister(uint16_t PHYAddress, uint16_t PHYReg)
{
uint32_t tmpreg = 0;
uint32_t timeout = 0;
/* Get the ETHERNET MACMIIAR value */
tmpreg = ETH->MACMIIAR;
/* Keep only the CSR Clock Range CR[2:0] bits value */
tmpreg &= ~MACMIIAR_CR_MASK;
/* Prepare the MII address register value */
tmpreg |= (((uint32_t)PHYAddress<<11) & ETH_MACMIIAR_PA); /* Set the PHY device address */
tmpreg |= (((uint32_t)PHYReg<<6) & ETH_MACMIIAR_MR); /* Set the PHY register address */
tmpreg &= ~ETH_MACMIIAR_MW; /* Set the read mode */
tmpreg |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
/* Write the result value into the MII Address register */
ETH->MACMIIAR = tmpreg;
/* Check for the Busy flag */
do
{
timeout++;
tmpreg = ETH->MACMIIAR;
} while ((tmpreg & ETH_MACMIIAR_MB) && (timeout < (uint32_t)PHY_READ_TO));
/* Return ERROR in case of timeout */
if(timeout == PHY_READ_TO)
{
return (uint16_t)ETH_ERROR;
}
/* Return data register value */
return (uint16_t)(ETH->MACMIIDR);
}
/*******************************************************************************
* @fn ETH_WritePHYRegister
*
* @brief Write PHY register
*
* @param PHYAddress - PHY address
* PHYReg - PHY register address
* PHYValue - Value will be written of PHY register
*
* @return Execution status
*/
uint32_t ETH_WritePHYRegister(uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue)
{
uint32_t tmpreg = 0;
uint32_t timeout = 0;
/* Get the ETHERNET MACMIIAR value */
tmpreg = ETH->MACMIIAR;
/* Keep only the CSR Clock Range CR[2:0] bits value */
tmpreg &= ~MACMIIAR_CR_MASK;
/* Prepare the MII register address value */
tmpreg |= (((uint32_t)PHYAddress<<11) & ETH_MACMIIAR_PA); /* Set the PHY device address */
tmpreg |= (((uint32_t)PHYReg<<6) & ETH_MACMIIAR_MR); /* Set the PHY register address */
tmpreg |= ETH_MACMIIAR_MW; /* Set the write mode */
tmpreg |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
/* Give the value to the MII data register */
ETH->MACMIIDR = PHYValue;
/* Write the result value into the MII Address register */
ETH->MACMIIAR = tmpreg;
/* Check for the Busy flag */
do
{
timeout++;
tmpreg = ETH->MACMIIAR;
} while ((tmpreg & ETH_MACMIIAR_MB) && (timeout < (uint32_t)PHY_WRITE_TO));
/* Return ERROR in case of timeout */
if(timeout == PHY_WRITE_TO)
{
return ETH_ERROR;
}
/* Return SUCCESS */
return ETH_SUCCESS;
}
/*******************************************************************************
* @fn ETH_DMAITConfig
*
* @brief Configuration DMA interrupt
*
* @param ETH_DMA_IT - Type of DMA interrupt
* NewState - Enable DMA interrupt or Disable DMA interrupt
*
* @return None
*/
void ETH_DMAITConfig(uint32_t ETH_DMA_IT, FunctionalState NewState)
{
if (NewState != DISABLE)
{
/* Enable the selected ETHERNET DMA interrupts */
ETH->DMAIER |= ETH_DMA_IT;
}
else
{
/* Disable the selected ETHERNET DMA interrupts */
ETH->DMAIER &= ~(uint32_t)ETH_DMA_IT;
}
}
/*******************************************************************************
* @fn ETH_DMAClearITPendingBit
*
* @brief Clear DMA interrupt flag
*
* @param ETH_DMA_IT - Type of DMA interrupt
*
* @return None
*/
void ETH_DMAClearITPendingBit(uint32_t ETH_DMA_IT)
{
/* Clear the selected ETHERNET DMA IT */
ETH->DMASR = (uint32_t) ETH_DMA_IT;
}
/*******************************************************************************
* @fn ETH_DMATxDescChainInit
*
* @brief transmit descriptor initialization
*
* @param DMARxDescTab - pointer to the transmit descriptor table
* RxBuff - pointer to the transmit buffer (transmit queue)
* RxBuffCount - Number of transmit descriptor or transmit queue
*
* @return None
*/
void ETH_DMATxDescChainInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t* TxBuff, uint32_t TxBuffCount)
{
uint8_t i = 0;
ETH_DMADESCTypeDef *DMATxDesc;
DMATxDescToSet = DMATxDescTab;
for(i = 0; i < TxBuffCount; i++)
{
DMATxDesc = DMATxDescTab + i;
DMATxDesc->Status = ETH_DMATxDesc_TCH | ETH_DMATxDesc_IC;
DMATxDesc->Buffer1Addr = (uint32_t)(&TxBuff[i * ETH_MAX_PACKET_SIZE]);
if(i < (TxBuffCount - 1))
{
DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab + i + 1);
}
else
{
DMATxDesc->Buffer2NextDescAddr = (uint32_t)DMATxDescTab;
}
}
ETH->DMATDLAR = (uint32_t)DMATxDescTab;
}
/*******************************************************************************
* @fn ETH_DMARxDescChainInit
*
* @brief Receive descriptor initialization
*
* @param DMARxDescTab - pointer to the receive descriptor table
* RxBuff - pointer to the receive buffer (receive queue)
* RxBuffCount - Number of receive descriptor or receive queue
*
* @return None
**/
void ETH_DMARxDescChainInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount)
{
uint8_t i = 0;
ETH_DMADESCTypeDef *DMARxDesc;
DMARxDescToGet = DMARxDescTab;
for(i = 0; i < RxBuffCount; i++)
{
DMARxDesc = DMARxDescTab + i;
DMARxDesc->Status = ETH_DMARxDesc_OWN;
DMARxDesc->ControlBufferSize = (uint32_t)ETH_MAX_PACKET_SIZE;
DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff[i * ETH_MAX_PACKET_SIZE]);
if(i < (RxBuffCount - 1))
{
DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab + i + 1);
}
else
{
DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab);
}
}
ETH->DMARDLAR = (uint32_t)DMARxDescTab;
}

View File

@ -0,0 +1,523 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_gpio.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn GPIOA_ModeCfg
*
* @brief GPIOA port pin mode configuration
*
* @param pin - PA0-PA15
* GPIO_Pin_0 - GPIO_Pin_15
* mode -
* GPIO_ModeIN_Floating - Floating input/high impedance input
* GPIO_ModeIN_PU_NSMT - Input with pull-up resistor
* GPIO_ModeIN_PD_NSMT - Input with pull-down resistor
* GPIO_ModeIN_PU_SMT - Schmitt input with pull-up resistor
* GPIO_ModeIN_PD_SMT - Schmitt input with pull-down resistor
* GPIO_Slowascent_PP_8mA - Low slope push-pull output, drive capability 8mA level
* GPIO_Slowascent_PP_16mA - Low slope push-pull output, drive capability 16mA level
* GPIO_Highspeed_PP_8mA - Fast push-pull output, drive capability 8mA level
* GPIO_Highspeed_PP_16mA - Fast push-pull output, drive capability 16mA level
* GPIO_ModeOut_OP_8mA - Push-pull output up to 8mA
* GPIO_ModeOut_OP_16mA - Push-pull output up to 16mA
*
* @return None
*/
void GPIOA_ModeCfg( UINT32 pin, GPIOModeTypeDef mode )
{
switch(mode)
{
case GPIO_ModeIN_Floating:
R32_PA_PD &= ~pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PU_NSMT:
R32_PA_SMT &=~ pin;
R32_PA_PD &= ~pin;
R32_PA_PU |= pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PD_NSMT:
R32_PA_SMT &=~ pin;
R32_PA_PD |= pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PU_SMT:
R32_PA_SMT |= pin;
R32_PA_PD &= ~pin;
R32_PA_PU |= pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PD_SMT:
R32_PA_SMT |= pin;
R32_PA_PD |= pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_Slowascent_PP_8mA:
R32_PA_SMT |= pin;
R32_PA_DRV &= ~pin;
R32_PA_PD &= ~pin;
R32_PA_DIR |= pin;
break;
case GPIO_Slowascent_PP_16mA:
R32_PA_SMT |= pin;
R32_PA_DRV |= pin;
R32_PA_PD &= ~pin;
R32_PA_DIR |= pin;
break;
case GPIO_Highspeed_PP_8mA:
R32_PA_SMT &= ~pin;
R32_PA_DRV &= ~pin;
R32_PA_PD &= ~pin;
R32_PA_DIR |= pin;
break;
case GPIO_Highspeed_PP_16mA:
R32_PA_SMT &= ~pin;
R32_PA_DRV |= pin;
R32_PA_PD &= ~pin;
R32_PA_DIR |= pin;
break;
case GPIO_ModeOut_OP_8mA:
R32_PA_DRV &= ~pin;
R32_PA_PD |= pin;
R32_PA_DIR |= pin;
break;
case GPIO_ModeOut_OP_16mA:
R32_PA_DRV |= pin;
R32_PA_PD |= pin;
R32_PA_DIR |= pin;
break;
default:
break;
}
}
/*******************************************************************************
* @fn GPIOB_ModeCfg
*
* @brief GPIOB port pin mode configuration
*
* @param pin - PB0-PB15
* GPIO_Pin_0 - GPIO_Pin_15
* mode -
* GPIO_ModeIN_Floating - Floating input/high impedance input
* GPIO_ModeIN_PU_NSMT - Input with pull-up resistor
* GPIO_ModeIN_PD_NSMT - Input with pull-down resistor
* GPIO_ModeIN_PU_SMT - Schmitt input with pull-up resistor
* GPIO_ModeIN_PD_SMT - Schmitt input with pull-down resistor
* GPIO_Slowascent_PP_8mA - Low slope push-pull output, drive capability 8mA level
* GPIO_Slowascent_PP_16mA - Low slope push-pull output, drive capability 16mA level
* GPIO_Highspeed_PP_8mA - Fast push-pull output, drive capability 8mA level
* GPIO_Highspeed_PP_16mA - Fast push-pull output, drive capability 16mA level
* GPIO_ModeOut_OP_8mA - Push-pull output up to 8mA
* GPIO_ModeOut_OP_16mA - Push-pull output up to 16mA
*
* @return None
*/
void GPIOB_ModeCfg( UINT32 pin, GPIOModeTypeDef mode )
{
switch(mode)
{
case GPIO_ModeIN_Floating:
R32_PB_PD &= ~pin;
R32_PB_PU &= ~pin;
R32_PB_DIR &= ~pin;
break;
case GPIO_ModeIN_PU_NSMT:
R32_PB_SMT &=~ pin;
R32_PB_PD &= ~pin;
R32_PB_PU |= pin;
R32_PB_DIR &= ~pin;
break;
case GPIO_ModeIN_PD_NSMT:
R32_PB_SMT &=~ pin;
R32_PB_PD |= pin;
R32_PB_PU &= ~pin;
R32_PB_DIR &= ~pin;
break;
case GPIO_ModeIN_PU_SMT:
R32_PB_SMT |= pin;
R32_PB_PD &= ~pin;
R32_PB_PU |= pin;
R32_PB_DIR &= ~pin;
break;
case GPIO_ModeIN_PD_SMT:
R32_PB_SMT |= pin;
R32_PB_PD |= pin;
R32_PB_PU &= ~pin;
R32_PB_DIR &= ~pin;
break;
case GPIO_Slowascent_PP_8mA:
R32_PB_SMT |= pin;
R32_PB_DRV &= ~pin;
R32_PB_PD &= ~pin;
R32_PB_DIR |= pin;
break;
case GPIO_Slowascent_PP_16mA:
R32_PB_SMT |= pin;
R32_PB_DRV |= pin;
R32_PB_PD &= ~pin;
R32_PB_DIR |= pin;
break;
case GPIO_Highspeed_PP_8mA:
R32_PB_SMT &= ~pin;
R32_PB_DRV &= ~pin;
R32_PB_PD &= ~pin;
R32_PB_DIR |= pin;
break;
case GPIO_Highspeed_PP_16mA:
R32_PB_SMT &= ~pin;
R32_PB_DRV |= pin;
R32_PB_PD &= ~pin;
R32_PB_DIR |= pin;
break;
case GPIO_ModeOut_OP_8mA:
R32_PB_DRV &= ~pin;
R32_PB_PD |= pin;
R32_PB_DIR |= pin;
break;
case GPIO_ModeOut_OP_16mA:
R32_PB_DRV |= pin;
R32_PB_PD |= pin;
R32_PB_DIR |= pin;
break;
default:
break;
}
}
/*******************************************************************************
* @fn GPIOA_ITModeCfg
*
* @brief GPIOA pin interrupt mode configuration
*
* @param pin - PA2-PA4
* mode -
* GPIO_ITMode_LowLevel - Low level trigger
* GPIO_ITMode_HighLevel - High level trigger
* GPIO_ITMode_FallEdge - Falling edge trigger
* GPIO_ITMode_RiseEdge - Rising edge trigger
*
* @return None
*/
void GPIOA_ITModeCfg( UINT32 pin, GPIOITModeTpDef mode )
{
switch( mode )
{
case GPIO_ITMode_LowLevel: // Low level trigger
R32_PA_DIR &= ~pin;
R8_GPIO_INT_MODE &= ~(pin>>2);
R8_GPIO_INT_POLAR &= ~(pin>>2);
break;
case GPIO_ITMode_HighLevel: // High level trigger
R32_PA_DIR &= ~pin;
R8_GPIO_INT_MODE &= ~(pin>>2);
R8_GPIO_INT_POLAR |= (pin>>2);
break;
case GPIO_ITMode_FallEdge: // Falling edge trigger
R32_PA_DIR &= ~pin;
R8_GPIO_INT_MODE |= (pin>>2);
R8_GPIO_INT_POLAR &= ~(pin>>2);
break;
case GPIO_ITMode_RiseEdge: // Rising edge trigger
R32_PA_DIR &= ~pin;
R8_GPIO_INT_MODE |= (pin>>2);
R8_GPIO_INT_POLAR |= (pin>>2);
break;
default :
break;
}
R8_GPIO_INT_FLAG = (pin>>2);
R8_GPIO_INT_ENABLE |= (pin>>2);
}
/*******************************************************************************
* @fn GPIOB_ITModeCfg
*
* @brief GPIOB pin interrupt mode configuration
*
* @param pin - PB3-PB4-PB11-PB12-PB15
* mode -
* GPIO_ITMode_LowLevel - Low level trigger
* GPIO_ITMode_HighLevel - High level trigger
* GPIO_ITMode_FallEdge - Falling edge trigger
* GPIO_ITMode_RiseEdge - Rising edge trigger
*
* @return None
*/
void GPIOB_ITModeCfg( UINT32 pin, GPIOITModeTpDef mode )
{
switch( mode )
{
case GPIO_ITMode_LowLevel: // Low level trigger
if(pin==GPIO_Pin_3)
{
R32_PB_DIR &= ~(1<<3);
R8_GPIO_INT_MODE &= ~(1<<3);
R8_GPIO_INT_POLAR &= ~(1<<3);
R8_GPIO_INT_FLAG = (1<<3);
R8_GPIO_INT_ENABLE |= (1<<3);
}
else if(pin==GPIO_Pin_4)
{
R32_PB_DIR &= ~(1<<4);
R8_GPIO_INT_MODE &= ~(1<<4);
R8_GPIO_INT_POLAR &= ~(1<<4);
R8_GPIO_INT_FLAG = (1<<4);
R8_GPIO_INT_ENABLE |= (1<<4);
}
else if(pin==GPIO_Pin_11)
{
R32_PB_DIR &= ~(1<<11);
R8_GPIO_INT_MODE &= ~(1<<5);
R8_GPIO_INT_POLAR &= ~(1<<5);
R8_GPIO_INT_FLAG = (1<<5);
R8_GPIO_INT_ENABLE |= (1<<5);
}
else if(pin==GPIO_Pin_12)
{
R32_PB_DIR &= ~(1<<12);
R8_GPIO_INT_MODE &= ~(1<<6);
R8_GPIO_INT_POLAR &= ~(1<<6);
R8_GPIO_INT_FLAG = (1<<6);
R8_GPIO_INT_ENABLE |= (1<<6);
}
else if(pin==GPIO_Pin_15)
{
R32_PB_DIR &= ~(1<<15);
R8_GPIO_INT_MODE &= ~(1<<7);
R8_GPIO_INT_POLAR &= ~(1<<7);
R8_GPIO_INT_FLAG = (1<<7);
R8_GPIO_INT_ENABLE |= (1<<7);
}
break;
case GPIO_ITMode_HighLevel: // High level trigger
if(pin==GPIO_Pin_3)
{
R32_PB_DIR &= ~(1<<3);
R8_GPIO_INT_MODE &= ~(1<<3);
R8_GPIO_INT_POLAR |= (1<<3);
R8_GPIO_INT_FLAG = (1<<3);
R8_GPIO_INT_ENABLE |= (1<<3);
}
else if(pin==GPIO_Pin_4)
{
R32_PB_DIR &= ~(1<<4);
R8_GPIO_INT_MODE &= ~(1<<4);
R8_GPIO_INT_POLAR |= (1<<4);
R8_GPIO_INT_FLAG = (1<<4);
R8_GPIO_INT_ENABLE |= (1<<4);
}
else if(pin==GPIO_Pin_11)
{
R32_PB_DIR &= ~(1<<11);
R8_GPIO_INT_MODE &= ~(1<<5);
R8_GPIO_INT_POLAR |= (1<<5);
R8_GPIO_INT_FLAG = (1<<5);
R8_GPIO_INT_ENABLE |= (1<<5);
}
else if(pin==GPIO_Pin_12)
{
R32_PB_DIR &= ~(1<<12);
R8_GPIO_INT_MODE &= ~(1<<6);
R8_GPIO_INT_POLAR |= (1<<6);
R8_GPIO_INT_FLAG = (1<<6);
R8_GPIO_INT_ENABLE |= (1<<6);
}
else if(pin==GPIO_Pin_15)
{
R32_PB_DIR &= ~(1<<15);
R8_GPIO_INT_MODE &= ~(1<<7);
R8_GPIO_INT_POLAR |= (1<<7);
R8_GPIO_INT_FLAG = (1<<7);
R8_GPIO_INT_ENABLE |= (1<<7);
}
break;
case GPIO_ITMode_FallEdge: // Falling edge trigger
if(pin==GPIO_Pin_3)
{
R32_PB_DIR &= ~(1<<3);
R8_GPIO_INT_MODE |= (1<<3);
R8_GPIO_INT_POLAR &= ~(1<<3);
R8_GPIO_INT_FLAG = (1<<3);
R8_GPIO_INT_ENABLE |= (1<<3);
}
else if(pin==GPIO_Pin_4)
{
R32_PB_DIR &= ~(1<<4);
R8_GPIO_INT_MODE |= (1<<4);
R8_GPIO_INT_POLAR &= ~(1<<4);
R8_GPIO_INT_FLAG = (1<<4);
R8_GPIO_INT_ENABLE |= (1<<4);
}
else if(pin==GPIO_Pin_11)
{
R32_PB_DIR &= ~(1<<11);
R8_GPIO_INT_MODE |= (1<<5);
R8_GPIO_INT_POLAR &= ~(1<<5);
R8_GPIO_INT_FLAG = (1<<5);
R8_GPIO_INT_ENABLE |= (1<<5);
}
else if(pin==GPIO_Pin_12)
{
R32_PB_DIR &= ~(1<<12);
R8_GPIO_INT_MODE |= (1<<6);
R8_GPIO_INT_POLAR &= ~(1<<6);
R8_GPIO_INT_FLAG = (1<<6);
R8_GPIO_INT_ENABLE |= (1<<6);
}
else if(pin==GPIO_Pin_15)
{
R32_PB_DIR &= ~(1<<15);
R8_GPIO_INT_MODE |= (1<<7);
R8_GPIO_INT_POLAR &= ~(1<<7);
R8_GPIO_INT_FLAG = (1<<7);
R8_GPIO_INT_ENABLE |= (1<<7);
}
break;
case GPIO_ITMode_RiseEdge: // Rising edge trigger
if(pin==GPIO_Pin_3)
{
R32_PB_DIR &= ~(1<<3);
R8_GPIO_INT_MODE |= (1<<3);
R8_GPIO_INT_POLAR |= (1<<3);
R8_GPIO_INT_FLAG = (1<<3);
R8_GPIO_INT_ENABLE |= (1<<3);
}
else if(pin==GPIO_Pin_4)
{
R32_PB_DIR &= ~(1<<4);
R8_GPIO_INT_MODE |= (1<<4);
R8_GPIO_INT_POLAR |= (1<<4);
R8_GPIO_INT_FLAG = (1<<4);
R8_GPIO_INT_ENABLE |= (1<<4);
}
else if(pin==GPIO_Pin_11)
{
R32_PB_DIR &= ~(1<<11);
R8_GPIO_INT_MODE |= (1<<5);
R8_GPIO_INT_POLAR |= (1<<5);
R8_GPIO_INT_FLAG = (1<<5);
R8_GPIO_INT_ENABLE |= (1<<5);
}
else if(pin==GPIO_Pin_12)
{
R32_PB_DIR &= ~(1<<12);
R8_GPIO_INT_MODE |= (1<<6);
R8_GPIO_INT_POLAR |= (1<<6);
R8_GPIO_INT_FLAG = (1<<6);
R8_GPIO_INT_ENABLE |= (1<<6);
}
else if(pin==GPIO_Pin_15)
{
R32_PB_DIR &= ~(1<<15);
R8_GPIO_INT_MODE |= (1<<7);
R8_GPIO_INT_POLAR |= (1<<7);
R8_GPIO_INT_FLAG = (1<<7);
R8_GPIO_INT_ENABLE |= (1<<7);
}
break;
default :
break;
}
}
/*******************************************************************************
* @fn GPIOPinRemap
*
* @brief Peripheral Function Pin Mapping
*
* @param s -
* ENABLE - pin map
* DISABLE - default pin
* perph -
* RB_PIN_UART0 - RXD0 - PB5 -> PA5
* - TXD0 - PB6 -> PA6
* RB_PIN_TMR2 - TMR2/PWM6/CAP2 - PA4 -> PB3
* RB_PIN_TMR1 - TMR1/PWM5/CAP1 - PB15 -> PB0
* RB_PIN_MII - Ethernet - RMII -> RGMII
* @return None
*/
void GPIOPinRemap( UINT8 s, UINT16 perph )
{
if( s ) R8_PIN_ALTERNATE |= perph;
else R8_PIN_ALTERNATE &= ~perph;
}
/*******************************************************************************
* @fn GPIOMco
*
* @brief GPIO MCO mode configuration
*
* @param s - ENABLE\DISABLE
* mode-
* MCO_125,
* MCO_25,
* MCO_2d5,
* @return None
*/
void GPIOMco( UINT8 s, UINT16 freq )
{
if(s)
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xa8;
R8_CLK_MOD_AUX = 0x10;
R8_CLK_MOD_AUX |=0x01;
R8_CLK_MOD_AUX |= freq;
}
else R8_CLK_MOD_AUX &= ~(1<<4);
}

View File

@ -0,0 +1,75 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_hspi.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn HSPI_Mode
*
* @brief DVP mode
*
* @param s - data width
* RB_HPIF_DAT8_MOD - 8-bit mode
* RB_HPIF_DAT16_MOD - 16-bit mode
* RB_HPIF_DAT32_MOD - 32-bit mode
* i - Operating mode
* UP_Mode - Enable upper mode
* DOWN_Mode - Enable downside mode
*
* @return None
*/
void HSPI_Mode( UINT8 s, HSPI_ModeTypeDef i)
{
R8_HSPI_CFG &= ~RB_HSPI_MSK_SIZE; //Restore default mode 8bit mode
if(s){
R8_HSPI_CFG |= s;
}
else{
R8_HSPI_CFG &= ~RB_HSPI_MSK_SIZE;
}
if(i){
R8_HSPI_CFG |= RB_HSPI_MODE;
}
else{
R8_HSPI_CFG &= ~RB_HSPI_MODE;
}
}
/*******************************************************************************
* @fn HSPI_INTCfg
*
* @brief HSPI interrupt configuration
*
* @param s - interrupt control status
* ENABLE - Enable corresponding interrupt
* DISABLE - Disable the corresponding interrupt
* i - interrupt type
* RB_HSPI_IE_T_DONE - Burst Sequence Transmit Complete Interrupt
* RB_HSPI_IE_R_DONE - Receive FIFO overflow interrupt
* RB_HSPI_IE_FIFO_OV - Single packet receive complete interrupt
* RB_HSPI_IE_B_DONE - Guaranteed Send Complete Interrupt
*
* @return None
*/
void HSPI_INTCfg( UINT8 s, UINT8 i )
{
if(s){
R8_HSPI_INT_EN |= i;
}
else{
R8_HSPI_INT_EN &= ~i;
}
}

View File

@ -0,0 +1,76 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_pwm.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn PWMX_CycleCfg
*
* @brief PWM0-PWM3 reference clock configuration
*
* @param cyc -
*
* @return None
*/
void PWMX_CycleCfg( PWMX_CycleTypeDef cyc )
{
switch( cyc )
{
case PWMX_Cycle_256:
R8_PWM_CTRL_CFG &= ~RB_PWM_CYCLE_SEL; //PWM configuration control register, clock cycle selection
break;
case PWMX_Cycle_255:
R8_PWM_CTRL_CFG |= RB_PWM_CYCLE_SEL;
break;
default :
break;
}
}
/*******************************************************************************
* @fn PWMX_ACTOUT
*
* @brief PWM0-PWM3 channel output waveform configuration
*
* @param ch - select channel of pwm
* refer to channel of PWM define
* da - effective pulse width
* pr - select wave polar
* refer to PWMX_PolarTypeDef
* s - control pwmx function
* ENABLE - Output PWM
* DISABLE - turn off PWM
* @return None
*/
void PWMX_ACTOUT( UINT8 ch, UINT8 da, PWMX_PolarTypeDef pr, UINT8 s)
{
UINT8 i;
if(s == DISABLE) R8_PWM_CTRL_MOD &= ~(ch); //Determine whether the PWM output is enabled
else
{
(pr)?(R8_PWM_CTRL_MOD|=(ch<<4)):(R8_PWM_CTRL_MOD&=~(ch<<4)); //PWM output polarity control 1: Default high level, low active; 0: Default low level, high active
for(i=0; i<4; i++){
if((ch>>i)&1) *((PUINT8V)((&R8_PWM0_DATA)+i)) = da;
}
R8_PWM_CTRL_MOD |= (ch);
}
}

View File

@ -0,0 +1,173 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_pwr.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn PWR_PeriphClkCfg
*
* @brief Peripheral Clock Control Bits
* @param s -
* ENABLE - Turn on the peripheral clock
* DISABLE - Turn off peripheral clock
* perph -
* please refer to Peripher CLK control bit define
* @return None
*/
void PWR_PeriphClkCfg( UINT8 s, UINT16 perph )
{
if( s == DISABLE )
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R32_SLEEP_CONTROL |= perph;
}
else
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R32_SLEEP_CONTROL &= ~perph;
}
R8_SAFE_ACCESS_SIG = 0;
}
/*******************************************************************************
* @fn PWR_PeriphWakeUpCfg
*
* @brief Sleep wakeup source configuration
*
* @param s -
* ENABLE - Turn on this peripheral's wake-from-sleep feature
* DISABLE - Turn off this peripheral sleep wake function
* perph -
* RB_SLP_USBHS_WAKE - USB2.0 is the wake-up source
* RB_SLP_USBSS_WAKE - USB3.0 is the wake-up source
* RB_SLP_GPIO_WAKE - GPIO is the wake-up source
* RB_SLP_ETH_WAKE - ETH is the wakeup source
* ALL - all of above
* @return None
*/
void PWR_PeriphWakeUpCfg( UINT8 s, UINT16 perph )
{
if( s == DISABLE )
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R8_SLP_WAKE_CTRL &= ~perph;
}
else
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R8_SLP_WAKE_CTRL |= perph;
}
R8_SAFE_ACCESS_SIG = 0;
}
/*******************************************************************************
* @fn LowPower_Idle
*
* @brief Low power consumption - Enter Idle mode with WFI instruction
*
* @return None
*/
void LowPower_Idle( void )
{
PFIC->SCTLR &= ~1<<2; // Set the SleepDeep field of the core PFIC SCTLR register to 0
__WFI(); // Execute __WFI() after setting the wake-up condition
}
/*******************************************************************************
* @fn LowPower_Idle_WFE
*
* @brief Low power consumption - Enter Idle mode with WFE instruction
*
* @return None
*/
void LowPower_Idle_WFE( void )
{
PFIC->SCTLR &= ~1<<2; // Set the SleepDeep field of the core PFIC SCTLR register to 0
__WFE(); // Execute __WFE() after setting the wake-up condition
}
/*******************************************************************************
* @fn LowPower_Halt
*
* @brief Low power consumption - Enter Halt mode with WFI instruction
*
* @return None
*/
void LowPower_Halt( void )
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R8_SLP_POWER_CTRL |= RB_SLP_USBHS_PWRDN; // Set RB_SLP_USBHS_PWRDN to 1
R8_SAFE_ACCESS_SIG = 0x00;
PFIC->SCTLR |= 1<<2; // Set the SleepDeep field of the core PFIC SCTLR register to 1
__WFI(); // Execute __WFI() after setting the wake-up condition
}
/*******************************************************************************
* @fn LowPower_Halt
*
* @brief Low power consumption - Enter Halt mode with WFE instruction
*
* @return None
*/
void LowPower_Halt_WFE( void )
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
R8_SLP_POWER_CTRL |= RB_SLP_USBHS_PWRDN; // Set RB_SLP_USBHS_PWRDN to 1
R8_SAFE_ACCESS_SIG = 0x00;
PFIC->SCTLR |= 1<<2; // Set the SleepDeep field of the core PFIC SCTLR register to 1
__WFE(); // Execute __WFE() after setting the wake-up condition
}
/*******************************************************************************
* @fn LowPower_Sleep
*
* @brief Low power consumption - Enter Sleep mode with WFI instruction
*
* @return None
*/
void LowPower_Sleep( void )
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
USBSS->LINK_CFG &= ~(0x1 << 12); // This bit should be set to 0 when USB3.0 enters low-power consumption
USBSS->LINK_CFG &= ~(0x1 << 3); // Cancel USB PHY RESET
R8_SLP_POWER_CTRL |= RB_SLP_USBHS_PWRDN; // Set RB_SLP_USBHS_PWRDN to 1
R8_SAFE_ACCESS_SIG = 0x00;
PFIC->SCTLR |= 1<<2; // Set the SleepDeep field of the core PFIC SCTLR register to 1
__WFI(); // Execute __WFI() after setting the wake-up condition
}
/*******************************************************************************
* @fn LowPower_Sleep
*
* @brief Low power consumption - Enter Sleep mode with WFE instruction
*
* @return None
*/
void LowPower_Sleep_WFE( void )
{
R8_SAFE_ACCESS_SIG = 0x57;
R8_SAFE_ACCESS_SIG = 0xA8;
USBSS->LINK_CFG &= ~(0x1 << 12); // This bit should be set to 0 when USB3.0 enters low-power consumption
USBSS->LINK_CFG &= ~(0x1 << 3); // Cancel USB PHY RESET
R8_SLP_POWER_CTRL |= RB_SLP_USBHS_PWRDN; // Set RB_SLP_USBHS_PWRDN to 1
R8_SAFE_ACCESS_SIG = 0x00;
PFIC->SCTLR |= 1<<2; // Set the SleepDeep field of the core PFIC SCTLR register to 1
__WFE(); // Execute __WFE() after setting the wake-up condition
}

View File

@ -0,0 +1,579 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_spi.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn SPI0_MasterDefInit
*
* @brief Host mode default initialization
*
* @return None
*/
void SPI0_MasterDefInit( void )
{
R8_SPI0_CLOCK_DIV = 4; //Main frequency clock divided by 4
R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR; //FIFO/counter/interrupt flag register is cleared to 0, write 1 to force clear or clear
R8_SPI0_CTRL_MOD = RB_SPI_MOSI_OE | RB_SPI_SCK_OE ; //MOSI pin and SCK pin output enable
R8_SPI0_CTRL_CFG |= RB_SPI_AUTO_IF; //Enable access to BUFFER/FIFO to automatically clear the flag
R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; //Do not start DMA mode
}
/*******************************************************************************
* @fn SPI0_DataMode
*
* @brief Set data flow mode
*
* @param m - data flow mode
*
* @return None
*/
void SPI0_DataMode( ModeBitOrderTypeDef m )
{
switch( m )
{
case Mode0_LowBitINFront: //Mode 0, low order first
R8_SPI0_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD;
R8_SPI0_CTRL_CFG |= RB_SPI_BIT_ORDER;
break;
case Mode0_HighBitINFront: //Mode 0, high bit first
R8_SPI0_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD;
R8_SPI0_CTRL_CFG &= ~RB_SPI_BIT_ORDER;
break;
case Mode3_LowBitINFront: //Mode 3, low bit first
R8_SPI0_CTRL_MOD |= RB_SPI_MST_SCK_MOD;
R8_SPI0_CTRL_CFG |= RB_SPI_BIT_ORDER;
break;
case Mode3_HighBitINFront: //Mode 3, high bit first
R8_SPI0_CTRL_MOD |= RB_SPI_MST_SCK_MOD;
R8_SPI0_CTRL_CFG &= ~RB_SPI_BIT_ORDER;
break;
default:
break;
}
}
/*******************************************************************************
* @fn SPI0_MasterSendByte
*
* @brief Send a single byte (buffer)
*
* @param d - send bytes
*
* @return None
*/
void SPI0_MasterSendByte( UINT8 d )
{
R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R8_SPI0_BUFFER = d;
while( !(R8_SPI0_INT_FLAG & RB_SPI_FREE) );
}
/*******************************************************************************
* @fn SPI0_MasterRecvByte
*
* @brief Receive a single byte (buffer)
*
* @return bytes received
*/
UINT8 SPI0_MasterRecvByte( void )
{
R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R8_SPI0_BUFFER = 0xFF; //start transfer
while( !(R8_SPI0_INT_FLAG & RB_SPI_FREE) );
return ( R8_SPI0_BUFFER );
}
/*******************************************************************************
* @fn SPI0_MasterTrans
*
* @brief Continuously send multiple bytes using FIFO
*
* @param pbuf: The first address of the data content to be sent
*
* @return None
*/
void SPI0_MasterTrans( UINT8 *pbuf, UINT16 len )
{
UINT16 sendlen;
sendlen = len;
R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; //Set data direction to output
R16_SPI0_TOTAL_CNT = sendlen; //Set the length of the data to be sent
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END;
while( sendlen )
{
if( R8_SPI0_FIFO_COUNT < SPI_FIFO_SIZE )
{
R8_SPI0_FIFO = *pbuf;
pbuf++;
sendlen--;
}
}
while( R8_SPI0_FIFO_COUNT != 0 ); //Wait for all the data in the FIFO to be sent
}
/*******************************************************************************
* @fn SPI0_MasterRecv
*
* @brief Receive multiple bytes continuously using FIFO
*
* @param pbuf: The first address of the data content to be sent
*
* @return None
**/
void SPI0_MasterRecv( UINT8 *pbuf, UINT16 len )
{
UINT16 readlen;
readlen = len;
R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; //Set data direction to input
R16_SPI0_TOTAL_CNT = len; //Set the length of the data to be received, the FIFO direction will start the transmission if the input length is not 0
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END;
while( readlen )
{
if( R8_SPI0_FIFO_COUNT )
{
*pbuf = R8_SPI0_FIFO;
pbuf++;
readlen--;
}
}
}
/*******************************************************************************
* @fn SPI0_MasterDMATrans
*
* @brief Continuously send data in DMA mode
*
* @param pbuf: The starting address of the data to be sent
*
* @return None
*/
void SPI0_MasterDMATrans( PUINT8 pbuf, UINT16 len)
{
R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R32_SPI0_DMA_BEG = (UINT32)pbuf;
R32_SPI0_DMA_END = (UINT32)(pbuf + len);
R16_SPI0_TOTAL_CNT = len;
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END|RB_SPI_IF_DMA_END;
R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END));
R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
}
/*******************************************************************************
* @fn SPI0_MasterDMARecv
*
* @brief Receive data continuously in DMA mode
*
* @param pbuf: The starting address for storing the data to be received
*
* @return None
**/
void SPI0_MasterDMARecv( PUINT8 pbuf, UINT16 len)
{
R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR;
R32_SPI0_DMA_BEG = (UINT32)pbuf;
R32_SPI0_DMA_END = (UINT32)(pbuf + len);
R16_SPI0_TOTAL_CNT = len;
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END|RB_SPI_IF_DMA_END;
R8_SPI0_CTRL_CFG |= RB_SPI_DMA_ENABLE;
while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END));
R8_SPI0_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
}
/*******************************************************************************
* @fn SPI0_SlaveInit
*
* @brief Device mode default initialization
*
* @return None
*/
void SPI0_SlaveInit( void )
{
R8_SPI0_CTRL_MOD = RB_SPI_ALL_CLEAR; //FIFO/counter/interrupt flag register is cleared to 0, write 1 to force clear or clear
R8_SPI0_CTRL_MOD = RB_SPI_MISO_OE | RB_SPI_MODE_SLAVE;
R8_SPI0_CTRL_CFG |= RB_SPI_AUTO_IF; //Enable access to BUFFER/FIFO to automatically clear the flag
}
/*******************************************************************************
* @fn SPI0_SlaveRecvByte
*
* @brief Slave mode, receive one byte of data
*
* @return received data
*/
UINT8 SPI0_SlaveRecvByte( void )
{
R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; //Set to input mode, receive data
while( R8_SPI0_FIFO_COUNT == 0 );
return R8_SPI0_FIFO;
}
/*******************************************************************************
* @fn SPI0_SlaveRecvByte
*
* @brief Slave mode, send one byte of data
*
* @return received data
**/
void SPI0_SlaveSendByte( UINT8 d )
{
R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; //Set data direction to output
R8_SPI0_FIFO = d;
while( R8_SPI0_FIFO_COUNT != 0 ); //Wait for the send to complete
}
/*******************************************************************************
* @fn SPI0_SlaveRecv
*
* @brief Slave mode, receive multi-byte data
*
* @param pbuf: Receive data storage starting address
*
* @return None
**/
void SPI0_SlaveRecv( PUINT8 pbuf, UINT16 len )
{
UINT16 revlen;
revlen = len;
R8_SPI0_CTRL_MOD |= RB_SPI_FIFO_DIR; //Set to input mode, receive data
R16_SPI0_TOTAL_CNT = revlen; //Assign a value to the SPI send and receive data total length register
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END; //SPI interrupt flag register All bytes transfer complete flag, write 1 to clear 0
while( revlen )
{
if( R8_SPI0_FIFO_COUNT ) //Byte count in the current FIFO
{
*pbuf = R8_SPI0_FIFO;
pbuf++;
revlen--;
}
}
}
/*******************************************************************************
* @fn SPI0_SlaveTrans
*
* @brief Slave mode, send multi-byte data
*
* @param pbuf: The first address of the data content to be sent
*
* @return None
*/
void SPI0_SlaveTrans( UINT8 *pbuf, UINT16 len )
{
UINT16 sendlen;
sendlen = len;
R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR; //Set data direction to output
R16_SPI0_TOTAL_CNT = sendlen; //Set the length of the data to be sent
R8_SPI0_INT_FLAG = RB_SPI_IF_CNT_END; //SPI interrupt flag register All bytes transfer complete flag, write 1 to clear 0
while( sendlen )
{
if( R8_SPI0_FIFO_COUNT < SPI_FIFO_SIZE ) //Compare the byte count size in the current FIFO
{
R8_SPI0_FIFO = *pbuf;
pbuf++;
sendlen--;
}
}
while( R8_SPI0_FIFO_COUNT != 0 ); //Wait for all the data in the FIFO to be sent
}
/*******************************************************************************
* @fn SPI1_MasterDefInit
*
* @brief Host mode default initialization
*
* @return None
*/
void SPI1_MasterDefInit( void )
{
R8_SPI1_CLOCK_DIV = 4; //Main frequency clock divided by 4
R8_SPI1_CTRL_MOD = RB_SPI_ALL_CLEAR;
R8_SPI1_CTRL_MOD = RB_SPI_MOSI_OE | RB_SPI_SCK_OE ;
R8_SPI1_CTRL_CFG |= RB_SPI_AUTO_IF;
R8_SPI1_CTRL_CFG &= ~RB_SPI_DMA_ENABLE; //Do not start DMA mode
//R8_SPI1_CTRL_CFG |= RB_SPI_DMA_ENABLE; //Start DMA mode
}
/*******************************************************************************
* @fn SPI1_DataMode
*
* @brief Set data flow mode
*
* @param m: data flow mode
*
* @return None
***/
void SPI1_DataMode( ModeBitOrderTypeDef m )
{
switch( m )
{
case Mode0_LowBitINFront:
R8_SPI1_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD;
R8_SPI1_CTRL_CFG |= RB_SPI_BIT_ORDER;
break;
case Mode0_HighBitINFront:
R8_SPI1_CTRL_MOD &= ~RB_SPI_MST_SCK_MOD;
R8_SPI1_CTRL_CFG &= ~RB_SPI_BIT_ORDER;
break;
case Mode3_LowBitINFront:
R8_SPI1_CTRL_MOD |= RB_SPI_MST_SCK_MOD;
R8_SPI1_CTRL_CFG |= RB_SPI_BIT_ORDER;
break;
case Mode3_HighBitINFront:
R8_SPI1_CTRL_MOD |= RB_SPI_MST_SCK_MOD;
R8_SPI1_CTRL_CFG &= ~RB_SPI_BIT_ORDER;
break;
default:
break;
}
}
/*******************************************************************************
* @fn SPI1_MasterSendByte
*
* @brief Send a single byte (buffer)
*
* @param d - send bytes
*
* @return None
*/
void SPI1_MasterSendByte( UINT8 d )
{
R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R8_SPI1_BUFFER = d;
while( !(R8_SPI1_INT_FLAG & RB_SPI_FREE) );
}
/*******************************************************************************
* @fn SPI1_MasterRecvByte
*
* @brief Receive a single byte (buffer)
*
* @return bytes received
*/
UINT8 SPI1_MasterRecvByte( void )
{
R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R8_SPI1_BUFFER = 0xFF; //start transfer
while( !(R8_SPI1_INT_FLAG & RB_SPI_FREE) );
return ( R8_SPI1_BUFFER );
}
/*******************************************************************************
* @fn SPI1_MasterTrans
*
* @brief Continuously send multiple bytes using FIFO
*
* @param pbuf - The first address of the data content to be sent
* len - The length of the data sent by the request, the maximum is 4095
* @return None
*/
void SPI1_MasterTrans( UINT8 *pbuf, UINT16 len )
{
UINT16 sendlen;
sendlen = len;
R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR; //Set data direction to output
R16_SPI1_TOTAL_CNT = sendlen; //Set the length of the data to be sent
R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END;
while( sendlen )
{
if( R8_SPI1_FIFO_COUNT < SPI_FIFO_SIZE )
{
R8_SPI1_FIFO = *pbuf;
pbuf++;
sendlen--;
}
}
while( R8_SPI1_FIFO_COUNT != 0 ); //Wait for all the data in the FIFO to be sent
}
/*******************************************************************************
* @fn SPI1_MasterRecv
*
* @brief Receive multiple bytes continuously using FIFO
*
* @param pbuf - The first address of the data content to be sent
* len - The length of the data sent by the request, the maximum is 4095
* @return None
**/
void SPI1_MasterRecv( UINT8 *pbuf, UINT16 len )
{
UINT16 readlen;
readlen = len;
R8_SPI1_CTRL_MOD |= RB_SPI_FIFO_DIR; //Set data direction to input
R16_SPI1_TOTAL_CNT = len; //Set the length of the data to be received, the FIFO direction will start the transmission if the input length is not 0
R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END;
while( readlen )
{
if( R8_SPI1_FIFO_COUNT )
{
*pbuf = R8_SPI1_FIFO;
pbuf++;
readlen--;
}
}
}
/*******************************************************************************
* @fn SPI1_MasterDMATrans
*
* @brief Continuously send data in DMA mode
*
* @param pbuf - The starting address of the data to be sent
* len - With send data length
* @return None
*/
void SPI1_MasterDMATrans( PUINT8 pbuf, UINT16 len)
{
R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R32_SPI1_DMA_BEG = (UINT32)pbuf;
R32_SPI1_DMA_END = (UINT32)(pbuf + len);
R16_SPI1_TOTAL_CNT = len;
R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END|RB_SPI_IF_DMA_END;
R8_SPI1_CTRL_CFG |= RB_SPI_DMA_ENABLE;
while(!(R8_SPI1_INT_FLAG & RB_SPI_IF_CNT_END));
R8_SPI1_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
}
/*******************************************************************************
* @fn SPI1_MasterDMARecv
*
* @brief Receive data continuously in DMA mode
*
* @param pbuf - The starting address for storing the data to be received
* len - Data length to be received
*
* @return None
*/
void SPI1_MasterDMARecv( PUINT8 pbuf, UINT16 len)
{
R8_SPI1_CTRL_MOD |= RB_SPI_FIFO_DIR;
R32_SPI1_DMA_BEG = (UINT32)pbuf;
R32_SPI1_DMA_END = (UINT32)(pbuf + len);
R16_SPI1_TOTAL_CNT = len;
R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END|RB_SPI_IF_DMA_END;
R8_SPI1_CTRL_CFG |= RB_SPI_DMA_ENABLE;
while(!(R8_SPI0_INT_FLAG & RB_SPI_IF_CNT_END));
R8_SPI1_CTRL_CFG &= ~RB_SPI_DMA_ENABLE;
}
/*******************************************************************************
* @fn SPI1_SlaveInit
*
* @brief Device mode default initialization
*
* @return None
*/
void SPI1_SlaveInit( void )
{
R8_SPI1_CTRL_MOD = RB_SPI_ALL_CLEAR;
R8_SPI1_CTRL_MOD = RB_SPI_MISO_OE | RB_SPI_MODE_SLAVE;
R8_SPI1_CTRL_CFG |= RB_SPI_AUTO_IF;
}
/*******************************************************************************
* @fn SPI1_SlaveRecvByte
*
* @brief Slave mode, receive one byte of data
*
* @return received data
*/
UINT8 SPI1_SlaveRecvByte( void )
{
R8_SPI1_CTRL_MOD |= RB_SPI_FIFO_DIR;
while( R8_SPI1_FIFO_COUNT == 0 );
return R8_SPI1_FIFO;
}
/*******************************************************************************
* @fn SPI1_SlaveRecvByte
*
* @brief Slave mode, receive one byte of data
*
* @return received data
*/
void SPI1_SlaveSendByte( UINT8 d )
{
R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
R8_SPI1_FIFO = d;
while( R8_SPI1_FIFO_COUNT != 0 ); //Wait for the send to complete
}
/*******************************************************************************
* @fn SPI1_SlaveRecv
* @brief Slave mode, receive multi-byte data
* @param pbuf - Receive data storage starting address
* len - Request to receive data length
* @return None
*/
void SPI1_SlaveRecv( PUINT8 pbuf, UINT16 len )
{
UINT16 revlen;
revlen = len;
R8_SPI1_CTRL_MOD |= RB_SPI_FIFO_DIR;
R16_SPI1_TOTAL_CNT = revlen;
R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END;
while( revlen )
{
if( R8_SPI1_FIFO_COUNT )
{
*pbuf = R8_SPI1_FIFO;
pbuf++;
revlen--;
}
}
}
/*******************************************************************************
* @fn SPI1_SlaveTrans
*
* @brief Slave mode, send multi-byte data
*
* @param pbuf - The first address of the data content to be sent
* len - The length of the data sent by the request, the maximum is 4095
* @return None
*/
void SPI1_SlaveTrans( UINT8 *pbuf, UINT16 len )
{
UINT16 sendlen;
sendlen = len;
R8_SPI1_CTRL_MOD &= ~RB_SPI_FIFO_DIR; //Set data direction to output
R16_SPI1_TOTAL_CNT = sendlen; //Set the length of the data to be sent
R8_SPI1_INT_FLAG = RB_SPI_IF_CNT_END;
while( sendlen )
{
if( R8_SPI1_FIFO_COUNT < SPI_FIFO_SIZE )
{
R8_SPI1_FIFO = *pbuf;
pbuf++;
sendlen--;
}
}
while( R8_SPI1_FIFO_COUNT != 0 ); //Wait for all the data in the FIFO to be sent
}

View File

@ -0,0 +1,198 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_sys.c
* Author : WCH
* Version : V1.0
* Date : 2024/01/14
* Description : This file contains all the functions prototypes for
* SystemCoreClock, UART Printf , Delay functions .
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
static uint8_t p_us = 0;
static uint16_t p_ms = 0;
/*******************************************************************************
* @fn Delay_Init
*
* @brief Initializes Delay Funcation.
*
* @param systemclck - system clock Hz
*
* @return None
**/
void Delay_Init(uint32_t systemclck)
{
p_us = systemclck / 8000000;
p_ms = (uint16_t)p_us * 1000;
}
/*******************************************************************************
* @fn mDelayuS
*
* @brief Microsecond Delay Time.
*
* @param n - Microsecond number.
*
* @return None
**/
void mDelayuS(uint32_t n)
{
uint32_t i;
SysTick->CNTFG &= ~(1 << 1);
i = (uint32_t)n * p_us;
SysTick->CMP = i;
SysTick->CTLR = (1 << 8) | (1 << 0);
while ((SysTick->CNTFG & (1 << 1)) != (1 << 1));
SysTick->CTLR = 0;
}
/*******************************************************************************
* @fn mDelaymS
*
* @brief Millisecond Delay Time.
*
* @param n - Millisecond number.
*
* @return None
**/
void mDelaymS(uint32_t n)
{
uint32_t i;
SysTick->CNTFG &= ~(1 << 1);
i = (uint32_t)n * p_ms;
SysTick->CMP = i;
SysTick->CTLR = (1 << 8) | (1 << 0);
while ((SysTick->CNTFG & (1 << 1)) != (1 << 1));
SysTick->CTLR = 0;
}
/*******************************************************************************
* @fn SYS_GetInfoSta
*
* @brief Get the current system information status
*
* @param i -
* @return stat
**/
UINT8 SYS_GetInfoSta(SYS_InfoStaTypeDef i)
{
return (R8_RST_BOOT_STAT & (1 << i));
}
/*******************************************************************************
* @fn SYS_ResetExecute
*
* @brief Perform a system software reset
*
* @return None
**/
void SYS_ResetExecute(void)
{
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_RST_WDOG_CTRL |= RB_SOFTWARE_RESET | 0x40;
R8_SAFE_ACCESS_SIG = 0;
}
/*******************************************************************************
* @fn WWDG_ITCfg
*
* @brief Watchdog timer overflow interrupt enable
*
* @param s -
* DISABLE - Overflow without interruption
* ENABLE - Overflow interrupt
*
* @return None
**/
void WWDG_ITCfg(UINT8 s)
{
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
if (s == DISABLE) R8_RST_WDOG_CTRL = (R8_RST_WDOG_CTRL & (~RB_WDOG_INT_EN)) | 0x40;
else R8_RST_WDOG_CTRL |= RB_WDOG_INT_EN | 0x40;
R8_SAFE_ACCESS_SIG = 0;
}
/*******************************************************************************
* @fn WWDG_ResetCfg
*
* @brief Watchdog timer reset function
*
* @param s -
* DISABLE - Overflow does not reset
* ENABLE - Overflow system reset
*
* @return None
**/
void WWDG_ResetCfg(UINT8 s)
{
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
if (s == DISABLE) R8_RST_WDOG_CTRL = (R8_RST_WDOG_CTRL & (~RB_WDOG_RST_EN)) | 0x40;
else R8_RST_WDOG_CTRL |= RB_WDOG_RST_EN | 0x40;
R8_SAFE_ACCESS_SIG = 0;
}
/*******************************************************************************
* @fn WWDG_ClearFlag
* @brief Clear watchdog interrupt flag, reload count value can also be cleared
* @param None
* @return None
**/
void WWDG_ClearFlag(void)
{
R8_SAFE_ACCESS_SIG = 0x57; // enable safe access mode
R8_SAFE_ACCESS_SIG = 0xa8;
R8_RST_WDOG_CTRL |= RB_WDOG_INT_FLAG | 0x40;
R8_SAFE_ACCESS_SIG = 0;
}
#if (defined DEBUG)
/*******************************************************************************
* @fn _write
*
* @brief Support Printf Function
*
* @param *buf: UART send Data.
* size - Data length
*
* @return size - Data length
**/
__attribute__((used)) int _write(int fd, char *buf, int size)
{
int i;
for (i = 0; i < size; i++)
{
#if DEBUG == Debug_UART0
while (R8_UART0_TFC == UART_FIFO_SIZE);
R8_UART0_THR = *buf++;
#elif DEBUG == Debug_UART1
while (R8_UART1_TFC == UART_FIFO_SIZE);
R8_UART1_THR = *buf++;
#elif DEBUG == Debug_UART2
while (R8_UART2_TFC == UART_FIFO_SIZE);
R8_UART2_THR = *buf++;
#elif DEBUG == Debug_UART3
while (R8_UART3_TFC == UART_FIFO_SIZE);
R8_UART3_THR = *buf++;
#endif
}
return size;
}
#endif

View File

@ -0,0 +1,269 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_timer.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/*******************************************************************************
* @fn TMR0_TimerInit
*
* @brief Counting Function on TIM PeriPheral
*
* @param t - the Most End Value counting to
*
* @return None
*/
void TMR0_TimerInit( UINT32 t )
{
R32_TMR0_CNT_END = t;
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT;
}
/*******************************************************************************
* @fn TMR1_TimerInit
*
* @brief Counting Function on TIM PeriPheral
*
* @param t - the Most End Value counting to
*
* @return None
*/
void TMR1_TimerInit( UINT32 t )
{
R32_TMR1_CNT_END = t;
R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT;
}
/*******************************************************************************
* @fn TMR2_TimerInit
*
* @brief Counting Function on TIM PeriPheral
*
* @param t - the Most End Value counting to
*
* @return None
*/
void TMR2_TimerInit( UINT32 t )
{
R32_TMR2_CNT_END = t;
R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN | RB_TMR_CAP_COUNT;
}
/*******************************************************************************
* @fn TMR0_EXTSignalCounterInit
*
* @brief external signal count
*
* @param c
*
* @return None
*/
void TMR0_EXTSignalCounterInit( UINT32 c )
{
R32_TMR0_CNT_END = c;
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_CTRL_MOD = RB_TMR_CAP_COUNT|RB_TMR_MODE_IN|RB_TMR_COUNT_EN;
}
/*******************************************************************************
* @fn TMR1_EXTSignalCounterInit
*
* @brief external signal count
*
* @param c
*
* @return None
*/
void TMR1_EXTSignalCounterInit( UINT32 c )
{
R32_TMR1_CNT_END = c;
R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR1_CTRL_MOD = RB_TMR_CAP_COUNT|RB_TMR_MODE_IN|RB_TMR_COUNT_EN;
}
/*******************************************************************************
* @fn TMR2_EXTSignalCounterInit
*
* @brief external signal count
*
* @param c
*
* @return None
*/
void TMR2_EXTSignalCounterInit( UINT32 c )
{
R32_TMR2_CNT_END = c;
R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR2_CTRL_MOD = RB_TMR_CAP_COUNT|RB_TMR_MODE_IN|RB_TMR_COUNT_EN;
}
/*******************************************************************************
* @fn TMR0_PWMInit
*
* @brief PWM Output Init
*
* @param pr-
* ts-
*
* @return None
*/
void TMR0_PWMInit( PWM_PolarTypeDef pr, PWM_RepeatTsTypeDef ts )
{
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN
|RB_TMR_OUT_EN
|(pr<<4)
|(ts<<6);
}
/*******************************************************************************
* @fn TMR1_PWMInit
*
* @brief PWM Output Init
*
* @param pr-
* ts-
*
* @return None
*/
void TMR1_PWMInit( PWM_PolarTypeDef pr, PWM_RepeatTsTypeDef ts )
{
R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN
|RB_TMR_OUT_EN
|(pr<<4)
|(ts<<6);
}
/*******************************************************************************
* @fn TMR2_PWMInit
*
* @brief PWM Output Init
*
* @param pr-
* ts-
*
* @return None
*/
void TMR2_PWMInit( PWM_PolarTypeDef pr, PWM_RepeatTsTypeDef ts )
{
R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN
|RB_TMR_OUT_EN
|(pr<<4)
|(ts<<6);
}
/*******************************************************************************
* @fn TMR0_CapInit
*
* @brief cap
*
* @param CapModeTypeDef
*
* @return None
*/
void TMR0_CapInit( CapModeTypeDef cap )
{
R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN \
|RB_TMR_MODE_IN \
|(cap<<6);
}
/*******************************************************************************
* @fn TMR1_CapInit
*
* @brief cap
*
* @param CapModeTypeDef
*
* @return None
*/
void TMR1_CapInit( CapModeTypeDef cap )
{
R8_TMR1_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR1_CTRL_MOD = RB_TMR_COUNT_EN \
|RB_TMR_MODE_IN \
|(cap<<6);
}
/*******************************************************************************
* @fn TMR2_CapInit
*
* @brief cap
*
* @param CapModeTypeDef
*
* @return None
*/
void TMR2_CapInit( CapModeTypeDef cap )
{
R8_TMR2_CTRL_MOD = RB_TMR_ALL_CLEAR;
R8_TMR2_CTRL_MOD = RB_TMR_COUNT_EN \
|RB_TMR_MODE_IN \
|(cap<<6);
}
/*******************************************************************************
* @fn TMR1_DMACfd
*
* @brief TMR DMA Configuration
*
* @param ENABLE/DISABLE
* startAddr
* endAddr
* DMAModeTypeDef
* @return None
**/
void TMR1_DMACfg( UINT8 s, UINT16 startAddr, UINT16 endAddr, DMAModeTypeDef m )
{
if(s == DISABLE){
R8_TMR1_CTRL_DMA = 0;
}
else{
if(m) R8_TMR1_CTRL_DMA = RB_TMR_DMA_LOOP|RB_TMR_DMA_ENABLE;
else R8_TMR1_CTRL_DMA = RB_TMR_DMA_ENABLE;
R32_TMR1_DMA_BEG = startAddr;
R32_TMR1_DMA_END = endAddr;
}
}
/*******************************************************************************
* @fn TMR2_DMACfd
*
* @brief TMR DMA Configuration
*
* @param ENABLE/DISABLE
* startAddr
* endAddr
* DMAModeTypeDef
* @return None
**/
void TMR2_DMACfg( UINT8 s, UINT16 startAddr, UINT16 endAddr, DMAModeTypeDef m )
{
if(s == DISABLE){
R8_TMR2_CTRL_DMA = 0;
}
else{
if(m) R8_TMR2_CTRL_DMA = RB_TMR_DMA_LOOP|RB_TMR_DMA_ENABLE;
else R8_TMR2_CTRL_DMA = RB_TMR_DMA_ENABLE;
R32_TMR2_DMA_BEG = startAddr;
R32_TMR2_DMA_END = endAddr;
}
}

View File

@ -0,0 +1,548 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CH56x_uart.c
* Author : WCH
* Version : V1.0
* Date : 2020/07/31
* Description :
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "CH56x_common.h"
/******************************************************************************
* @fn UART0_DefInit
*
* @brief Serial port default initialization configuration: FIFO enabled, trigger point byte count, serial port data
* length setting, baud rate and frequency division coefficient
*
* @return None
*/
void UART0_DefInit(void)
{
R8_UART0_DIV = 1;
UART0_BaudRateCfg(115200);
R8_UART0_FCR =
(2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 4 bytes
R8_UART0_LCR = RB_LCR_WORD_SZ;
R8_UART0_IER = RB_IER_TXD_EN;
}
/*******************************************************************************
* @fn UART1_DefInit
*
* @brief Serial port default initialization configuration: FIFO enabled, trigger point byte count, serial port data
*length setting, baud rate and frequency division coefficient
*
* @return None
**/
void UART1_DefInit(void)
{
R8_UART1_DIV = 1;
UART1_BaudRateCfg(115200);
R8_UART1_FCR =
(2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 4 bytes
R8_UART1_LCR = RB_LCR_WORD_SZ;
R8_UART1_IER = RB_IER_TXD_EN;
}
/*******************************************************************************
* @fn UART2_DefInit
*
* @brief Serial port default initialization configuration: FIFO enabled, trigger point byte count, serial port data
* length setting, baud rate and frequency division coefficient
*
* @return None
*/
void UART2_DefInit(void)
{
R8_UART2_DIV = 1;
UART2_BaudRateCfg(115200);
R8_UART2_FCR =
(2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 4 bytes
R8_UART2_LCR = RB_LCR_WORD_SZ;
R8_UART2_IER = RB_IER_TXD_EN;
}
/*******************************************************************************
* @fn UART3_DefInit
*
* @brief Serial port default initialization configuration: FIFO enabled, trigger point byte count, serial port data
* length setting, baud rate and frequency division coefficient
*
* @return None
*/
void UART3_DefInit(void)
{
R8_UART3_DIV = 1;
UART3_BaudRateCfg(115200);
R8_UART3_FCR =
(2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO open, trigger point 4 bytes
R8_UART3_LCR = RB_LCR_WORD_SZ;
R8_UART3_IER = RB_IER_TXD_EN;
}
/*******************************************************************************
* @fn UART0_BaudRateCfg
*
* @brief Serial port baud rate configuration
*
* @return None
*/
void UART0_BaudRateCfg(UINT32 baudrate)
{
UINT32 x;
x = 10 * (FREQ_SYS * 2 / R8_UART0_DIV) / 16 / baudrate;
x = (x + 5) / 10;
R16_UART0_DL = (UINT16)x;
}
/*******************************************************************************
* @fn UART1_BaudRateCfg
*
* @brief Serial port baud rate configuration
*
* @return None
*/
void UART1_BaudRateCfg(UINT32 baudrate)
{
UINT32 x;
x = 10 * (FREQ_SYS * 2 / R8_UART1_DIV) / 16 / baudrate;
x = (x + 5) / 10;
R16_UART1_DL = (UINT16)x;
}
/*******************************************************************************
* @fn UART2_BaudRateCfg
*
* @brief Serial port baud rate configuration
*
* @return None
*/
void UART2_BaudRateCfg(UINT32 baudrate)
{
UINT32 x;
x = 10 * (FREQ_SYS * 2 / R8_UART2_DIV) / 16 / baudrate;
x = (x + 5) / 10;
R16_UART2_DL = (UINT16)x;
}
/*******************************************************************************
* @fn UART3_BaudRateCfg
*
* @brief Serial port baud rate configuration
*
* @return None
*/
void UART3_BaudRateCfg(UINT32 baudrate)
{
UINT32 x;
x = 10 * (FREQ_SYS * 2 / R8_UART3_DIV) / 16 / baudrate;
x = (x + 5) / 10;
R16_UART3_DL = (UINT16)x;
}
/*******************************************************************************
* @fn UART0_ByteTrigCfg
*
* @brief Serial byte trigger interrupt configuration
*
* @param b - trigger bytes
* refer to UARTByteTRIGTypeDef
* @return None
*/
void UART0_ByteTrigCfg(UARTByteTRIGTypeDef b)
{
R8_UART0_FCR = (R8_UART0_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6);
}
/*******************************************************************************
* @fn UART1_ByteTrigCfg
*
* @brief Serial byte trigger interrupt configuration
*
* @param b - trigger bytes
* refer to UARTByteTRIGTypeDef
* @return None
**/
void UART1_ByteTrigCfg(UARTByteTRIGTypeDef b)
{
R8_UART1_FCR = (R8_UART1_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6);
}
/*******************************************************************************
* @fn UART2_ByteTrigCfg
*
* @brief Serial byte trigger interrupt configuration
*
* @param b - trigger bytes
* refer to UARTByteTRIGTypeDef
* @return None
*/
void UART2_ByteTrigCfg(UARTByteTRIGTypeDef b)
{
R8_UART2_FCR = (R8_UART2_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6);
}
/*******************************************************************************
* @fn UART3_ByteTrigCfg
*
* @brief Serial byte trigger interrupt configuration
*
* @param b - trigger bytes
* refer to UARTByteTRIGTypeDef
* @return None
***/
void UART3_ByteTrigCfg(UARTByteTRIGTypeDef b)
{
R8_UART3_FCR = (R8_UART3_FCR & ~RB_FCR_FIFO_TRIG) | (b << 6);
}
/*******************************************************************************
* @fn UART0_INTCfg
*
* @brief Serial port interrupt configuration
*
* @param s - interrupt control status
* ENABLE - Enable the corresponding interrupt
* DISABLE - Disable the corresponding interrupt
* i - interrupt type
* RB_IER_MODEM_CHG - Modem input status change interrupt enable bit (supported on UART0 only)
* RB_IER_LINE_STAT - Receive Line Status Interrupt
* RB_IER_THR_EMPTY - Send Holding Register Empty Interrupt
* RB_IER_RECV_RDY - receive data interrupt
* @return None
**/
void UART0_INTCfg(UINT8 s, UINT8 i)
{
if (s)
{
R8_UART0_IER |= i;
R8_UART0_MCR |= RB_MCR_INT_OE;
}
else
{
R8_UART0_IER &= ~i;
}
}
/*******************************************************************************
* @fn UART1_INTCfg
*
* @brief Serial port interrupt configuration
*
* @param s - interrupt control status
* ENABLE - Enable the corresponding interrupt
* DISABLE - Disable the corresponding interrupt
* i - interrupt type
* RB_IER_MODEM_CHG - Modem input status change interrupt enable bit (supported on UART0 only)
* RB_IER_LINE_STAT - Receive Line Status Interrupt
* RB_IER_THR_EMPTY - Send Holding Register Empty Interrupt
* RB_IER_RECV_RDY - receive data interrupt
* @return None
**/
void UART1_INTCfg(UINT8 s, UINT8 i)
{
if (s)
{
R8_UART1_IER |= i;
R8_UART1_MCR |= RB_MCR_INT_OE;
}
else
{
R8_UART1_IER &= ~i;
}
}
/*******************************************************************************
* @fn UART2_INTCfg
*
* @brief Serial port interrupt configuration
*
* @param s - interrupt control status
* ENABLE - Enable the corresponding interrupt
* DISABLE - Disable the corresponding interrupt
* i - interrupt type
* RB_IER_MODEM_CHG - Modem input status change interrupt enable bit (supported on UART0 only)
* RB_IER_LINE_STAT - Receive Line Status Interrupt
* RB_IER_THR_EMPTY - Send Holding Register Empty Interrupt
* RB_IER_RECV_RDY - receive data interrupt
* @return None
**/
void UART2_INTCfg(UINT8 s, UINT8 i)
{
if (s)
{
R8_UART2_IER |= i;
R8_UART2_MCR |= RB_MCR_INT_OE;
}
else
{
R8_UART2_IER &= ~i;
}
}
/*******************************************************************************
* @fn UART3_INTCfg
*
* @brief Serial port interrupt configuration
*
* @param s - interrupt control status
* ENABLE - Enable the corresponding interrupt
* DISABLE - Disable the corresponding interrupt
* i - interrupt type
* RB_IER_MODEM_CHG - Modem input status change interrupt enable bit (supported on UART0 only)
* RB_IER_LINE_STAT - Receive Line Status Interrupt
* RB_IER_THR_EMPTY - Send Holding Register Empty Interrupt
* RB_IER_RECV_RDY - receive data interrupt
* @return None
**/
void UART3_INTCfg(UINT8 s, UINT8 i)
{
if (s)
{
R8_UART3_IER |= i;
R8_UART3_MCR |= RB_MCR_INT_OE;
}
else
{
R8_UART3_IER &= ~i;
}
}
/*******************************************************************************
* @fn UART0_Reset
*
* @brief Serial port software reset
*
* @return None
**/
void UART0_Reset(void)
{
R8_UART0_IER = RB_IER_RESET;
}
/*******************************************************************************
* @fn UART1_Reset
*
* @brief Serial port software reset
*
* @return None
**/
void UART1_Reset(void)
{
R8_UART1_IER = RB_IER_RESET;
}
/*******************************************************************************
* @fn UART2_Reset
*
* @brief Serial port software reset
*
* @return None
**/
void UART2_Reset(void)
{
R8_UART2_IER = RB_IER_RESET;
}
/*******************************************************************************
* @fn UART3_Reset
*
* @brief Serial port software reset
*
* @return None
**/
void UART3_Reset(void)
{
R8_UART3_IER = RB_IER_RESET;
}
/*******************************************************************************
* @fn UART0_SendString
*
* @brief Serial multi-byte transmission
*
* @param buf - The first address of the data content to be sent
* l - length of data to be sent
* @return None
*/
void UART0_SendString(PUINT8 buf, UINT16 l)
{
UINT16 len = l;
while (len)
{
if (R8_UART0_TFC != UART_FIFO_SIZE)
{
R8_UART0_THR = *buf++;
len--;
}
}
}
/*******************************************************************************
* @fn UART1_SendString
*
* @brief Serial multi-byte transmission
*
* @param buf - The first address of the data content to be sent
* l - length of data to be sent
* @return None
*/
void UART1_SendString(PUINT8 buf, UINT16 l)
{
UINT16 len = l;
while (len)
{
if (R8_UART1_TFC != UART_FIFO_SIZE)
{
R8_UART1_THR = *buf++;
len--;
}
}
}
/*******************************************************************************
* @fn UART2_SendString
*
* @brief Serial multi-byte transmission
*
* @param buf - The first address of the data content to be sent
* l - length of data to be sent
* @return None
*/
void UART2_SendString(PUINT8 buf, UINT16 l)
{
UINT16 len = l;
while (len)
{
if (R8_UART2_TFC != UART_FIFO_SIZE)
{
R8_UART2_THR = *buf++;
len--;
}
}
}
/*******************************************************************************
* @fn UART3_SendString
*
* @brief Serial multi-byte transmission
*
* @param buf - The first address of the data content to be sent
* l - length of data to be sent
* @return None
*/
void UART3_SendString(PUINT8 buf, UINT16 l)
{
UINT16 len = l;
while (len)
{
if (R8_UART3_TFC != UART_FIFO_SIZE)
{
R8_UART3_THR = *buf++;
len--;
}
}
}
/*******************************************************************************
* @fn UART0_RecvString
*
* @brief Serial port read multibyte
*
* @param buf - The first address of the read data storage buffer
*
* @return read data length
*/
UINT16 UART0_RecvString(PUINT8 buf)
{
UINT16 len = 0;
while (R8_UART0_RFC)
{
*buf++ = R8_UART0_RBR;
len++;
}
return (len);
}
/*******************************************************************************
* @fn UART1_RecvString
*
* @brief Serial port read multibyte
*
* @param buf - The first address of the read data storage buffer
*
* @return read data length
*/
UINT16 UART1_RecvString(PUINT8 buf)
{
UINT16 len = 0;
while (R8_UART1_RFC)
{
*buf++ = R8_UART1_RBR;
len++;
}
return (len);
}
/*******************************************************************************
* @fn UART2_RecvString
*
* @brief Serial port read multibyte
*
* @param buf - The first address of the read data storage buffer
*
* @return read data length
*/
UINT16 UART2_RecvString(PUINT8 buf)
{
UINT16 len = 0;
while (R8_UART2_RFC)
{
*buf++ = R8_UART2_RBR;
len++;
}
return (len);
}
/*******************************************************************************
* @fn UART3_RecvString
*
* @brief Serial port read multibyte
*
* @param buf - The first address of the read data storage buffer
*
* @return read data length
*/
UINT16 UART3_RecvString(PUINT8 buf)
{
UINT16 len = 0;
while (R8_UART3_RFC)
{
*buf++ = R8_UART3_RBR;
len++;
}
return (len);
}

View File

@ -0,0 +1,17 @@
SRC_FILES := \
CH56x_bus8.c \
CH56x_clk.c \
CH56x_dvp.c \
CH56x_ecdc.c \
CH56x_emmc.c \
CH56x_eth.c \
CH56x_gpio.c \
CH56x_hspi.c \
CH56x_pwm.c \
CH56x_pwr.c \
CH56x_spi.c \
CH56x_sys.c \
CH56x_timer.c \
CH56x_uart.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_uart.h
* @brief define rvstar uart function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-08-01
*/
#ifndef CONNECT_UART_H
#define CONNECT_UART_H
#include <device.h>
#ifdef __cplusplus
extern "C" {
#endif
union _uart_mcr
{
uint8_t reg;
struct
{
uint8_t dtr : 1; // B.0 : RW, DTR output (UART0 only)
uint8_t rts : 1; // B.1 : RW, RTS output (UART0 only)
uint8_t out1 : 1; // B.2 : RW, user defined modem control (UART0 only)
uint8_t int_oe : 1; // B.3 : RW, interrupt output enable / OUT2
uint8_t loop : 1; // B.4 : RW, enable internal loop test (UART0 only)
uint8_t au_flow_en : 1; // B.5 : RW, enable CTS/RTS autoflow control
uint8_t tnow : 1; // B.6 : RW, enable DTR TNOW output (UART0 only)
uint8_t half : 1; // B.7 : RW, enable half-duplex mode (UART0 only)
};
};
union _uart_ier
{
uint8_t reg;
struct
{
uint8_t recv_rdy : 1; // B.0 : RW, enable rx data ready intr
uint8_t thr_empty : 1; // B.1 : RW, enable THR empty intr
uint8_t line_stat : 1; // B.2 : RW, enable rx line status intr
uint8_t modem_chg : 1; // B.3 : RW, enable modem status change intr (UART0 only)
uint8_t dtr_en : 1; // B.4 : RW, DTR/TNOW output pin enable (UART0 only)
uint8_t rts_en : 1; // B.5 : RW, RTS output pin enable (UART0 only)
uint8_t txd_en : 1; // B.6 : RW, TXD pin enable
uint8_t reset : 1; // B.7 : WZ, software reset control, active high, auto clear
};
};
union _uart_fcr
{
uint8_t reg;
struct
{
uint8_t fifo_en : 1; // B.0 : RW, FIFO enable
uint8_t rx_fifo_clr : 1; // B.1 : WZ, write 1 to clear rx FIFO, auto clear
uint8_t tx_fifo_clr : 1; // B.2 : WZ, write 1 to clear tx FIFO, auto clear
uint8_t resv_3 : 3;
uint8_t fifo_trig : 2; // B.7-6 : RW, rx FIFO trigger level, 1/2/4/7 bytes
};
};
union _uart_lcr
{
uint8_t reg;
struct
{
uint8_t word_sz : 2; // B.1-0 : RW, word bit length, 5/6/7/8 bits
uint8_t stop_bit : 1; // B.2 : RW, stop bit length, 1/2 bits
uint8_t par_en : 1; // B.3 : RW, parity enable
uint8_t par_mod : 2; // B.5-4 : RW, parity mode, odd/even/mark/space
uint8_t break_en : 1; // B.6 : RW, force BREAK line condition
uint8_t dlab : 1; // B.7 : RW, user defined general purpose bit
};
};
#define LCR_DATA_BITS_5 0
#define LCR_DATA_BITS_6 1
#define LCR_DATA_BITS_7 2
#define LCR_DATA_BITS_8 3
#define LCR_STOP_BITS_1 0
#define LCR_STOP_BITS_2 1
#define LCR_PARITY_ODD 0
#define LCR_PARITY_EVEN 1
#define LCR_PARITY_MARK 2
#define LCR_PARITY_SPACE 3
union _uart_iir
{
uint8_t reg;
struct
{
uint8_t int_mask : 4; // B.3-0 : RO, interrupt mask (intr if B.0 is 0)
uint8_t resv_4 : 2;
uint8_t fifo_id : 2; // B.7-6 : RO, FIFO enabled flag
};
};
union _uart_lsr
{
uint8_t reg;
struct
{
uint8_t data_rdy : 1; // B.0 : RO, rx FIFO data ready
uint8_t over_err : 1; // B.1 : RZ, rx FIFO data overrun
uint8_t par_err : 1; // B.2 : RZ, rx parity error
uint8_t frame_err : 1; // B.3 : RZ, rx frame error
uint8_t break_err : 1; // B.4 : RZ, rx BREAK detected
uint8_t tx_fifo_emp : 1; // B.5 : RO, tx FIFO empty
uint8_t tx_all_emp : 1; // B.6 : RO, THR/TSR all empty
uint8_t err_rx_fifo : 1; // B.7 : RO, PAR/FRAME/BREAK ERR in rx FIFO
};
};
union _uart_msr
{
uint8_t reg;
struct
{
uint8_t cts_chg : 1; // B.0 : RZ, CTS input changed
uint8_t dsr_chg : 1; // B.1 : RZ, DSR input changed
uint8_t ri_chg : 1; // B.2 : RZ, RI input changed
uint8_t dcd_chg : 1; // B.3 : RZ, DCD input changed
uint8_t cts : 1; // B.4 : RO, CTS action status
uint8_t dsr : 1; // B.5 : RO, DSR action status
uint8_t ri : 1; // B.6 : RO, RI action status
uint8_t dcd : 1; // B.7 : RO, DCD action status
};
};
struct uart_registers
{
union _uart_mcr MCR;
union _uart_ier IER;
union _uart_fcr FCR;
union _uart_lcr LCR;
union _uart_iir IIR;
union _uart_lsr LSR;
union _uart_lsr MSR;
uint8_t resv_7;
union
{
uint8_t RBR;
uint8_t THR;
};
uint8_t resv_9;
uint8_t RFC;
uint8_t TFC;
uint16_t DL;
uint8_t DIV;
uint8_t ADR;
} __packed;
int InitHwUart(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,14 @@
menuconfig BSP_USING_UART1
bool "Enable UART1"
default y
if BSP_USING_UART1
config SERIAL_BUS_NAME_1
string "serial bus name"
default "uart1"
config SERIAL_DRV_NAME_1
string "serial bus driver name"
default "uart1_drv"
config SERIAL_1_DEVICE_NAME_0
string "serial bus device name"
default "uart1_dev1"
endif

View File

@ -0,0 +1,4 @@
SRC_FILES := connect_uart.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,386 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan
* PSL v2. You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
* Mulan PSL v2 for more details.
*/
/**
* @file connect_usart.c
* @brief support ch569 uart function and register to bus framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2025-04-07
*/
#include <xizi.h>
#include "xsconfig.h"
#include "CH56x_common.h"
#include "ch56x_it.h"
#include "board.h"
#include "connect_uart.h"
/* uart driver */
static void SerialCfgParamCheck(struct SerialCfgParam *serial_cfg_default, struct SerialCfgParam *serial_cfg_new) {
struct SerialDataCfg *data_cfg_default = &serial_cfg_default->data_cfg;
struct SerialDataCfg *data_cfg_new = &serial_cfg_new->data_cfg;
if ((data_cfg_default->serial_baud_rate != data_cfg_new->serial_baud_rate) && (data_cfg_new->serial_baud_rate)) {
data_cfg_default->serial_baud_rate = data_cfg_new->serial_baud_rate;
}
if ((data_cfg_default->serial_bit_order != data_cfg_new->serial_bit_order) && (data_cfg_new->serial_bit_order)) {
data_cfg_default->serial_bit_order = data_cfg_new->serial_bit_order;
}
if ((data_cfg_default->serial_buffer_size != data_cfg_new->serial_buffer_size) &&
(data_cfg_new->serial_buffer_size)) {
data_cfg_default->serial_buffer_size = data_cfg_new->serial_buffer_size;
}
if ((data_cfg_default->serial_data_bits != data_cfg_new->serial_data_bits) && (data_cfg_new->serial_data_bits)) {
data_cfg_default->serial_data_bits = data_cfg_new->serial_data_bits;
}
if ((data_cfg_default->serial_invert_mode != data_cfg_new->serial_invert_mode) &&
(data_cfg_new->serial_invert_mode)) {
data_cfg_default->serial_invert_mode = data_cfg_new->serial_invert_mode;
}
if ((data_cfg_default->serial_parity_mode != data_cfg_new->serial_parity_mode) &&
(data_cfg_new->serial_parity_mode)) {
data_cfg_default->serial_parity_mode = data_cfg_new->serial_parity_mode;
}
if ((data_cfg_default->serial_stop_bits != data_cfg_new->serial_stop_bits) && (data_cfg_new->serial_stop_bits)) {
data_cfg_default->serial_stop_bits = data_cfg_new->serial_stop_bits;
}
if ((data_cfg_default->serial_timeout != data_cfg_new->serial_timeout) && (data_cfg_new->serial_timeout)) {
data_cfg_default->serial_timeout = data_cfg_new->serial_timeout;
}
}
static void UartIsr(struct SerialDriver *serial_drv, struct SerialHardwareDevice *serial_dev) {
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
struct uart_registers *uxreg = (struct uart_registers *)serial_cfg->hw_cfg.serial_register_base;
if (UART_II_RECV_RDY == uxreg->IIR.int_mask) {
SerialSetIsr(serial_dev, SERIAL_EVENT_RX_IND);
PFIC_ClearPendingIRQ(serial_cfg->hw_cfg.serial_irq_interrupt);
}
}
static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInfo *configure_info) {
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
if (serial_cfg_new->data_cfg.dev_recv_callback) {
BusDevRecvCallback(&(serial_dev->haldev), serial_cfg_new->data_cfg.dev_recv_callback);
}
}
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;
// config serial reg
struct uart_registers *uxreg = (struct uart_registers *)serial_cfg->hw_cfg.serial_register_base;
union _uart_fcr fcr;
union _uart_lcr lcr;
uint32_t x;
uint32_t t = FREQ_SYS;
// x = 10 * sys_hclk_get() / 8 / serial_cfg->data_cfg.serial_baud_rate;
x = 10 * t / 8 / serial_cfg->data_cfg.serial_baud_rate;
x = (x + 5) / 10;
uxreg->DL = x;
uxreg->DIV = 1;
lcr.reg = 0;
switch (serial_cfg->data_cfg.serial_data_bits)
{
case DATA_BITS_5:
lcr.word_sz = LCR_DATA_BITS_5;
break;
case DATA_BITS_6:
lcr.word_sz = LCR_DATA_BITS_6;
break;
case DATA_BITS_7:
lcr.word_sz = LCR_DATA_BITS_7;
break;
case DATA_BITS_8:
default:
lcr.word_sz = LCR_DATA_BITS_8;
break;
}
switch (serial_cfg->data_cfg.serial_stop_bits)
{
case STOP_BITS_2:
lcr.stop_bit = LCR_STOP_BITS_2;
break;
case STOP_BITS_1:
default:
lcr.stop_bit = LCR_STOP_BITS_1;
break;
}
switch (serial_cfg->data_cfg.serial_parity_mode)
{
case PARITY_ODD:
lcr.par_mod = LCR_PARITY_ODD;
lcr.par_en = 1;
break;
case PARITY_EVEN:
lcr.par_mod = LCR_PARITY_EVEN;
lcr.par_en = 1;
break;
case PARITY_NONE:
default:
lcr.par_en = 0;
break;
}
uxreg->LCR.reg = lcr.reg;
fcr.reg = RB_FCR_FIFO_EN | RB_FCR_RX_FIFO_CLR | RB_FCR_TX_FIFO_CLR;
fcr.fifo_trig = UART_1BYTE_TRIG;
uxreg->FCR.reg = fcr.reg;
/* TXD pin output enable */
uxreg->IER.txd_en = 1;
return EOK;
}
static uint32 SerialConfigure(struct SerialDriver *serial_drv, int serial_operation_cmd) {
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct uart_registers *uxreg = (struct uart_registers *)serial_cfg->hw_cfg.serial_register_base;
switch (serial_operation_cmd) {
case OPER_CLR_INT:
uxreg->IER.recv_rdy = 0;
uxreg->IER.line_stat = 0;
uxreg->IER.thr_empty = 0;
PFIC_DisableIRQ(serial_cfg->hw_cfg.serial_irq_interrupt);
break;
case OPER_SET_INT:
uxreg->FCR.fifo_trig = UART_1BYTE_TRIG;
uxreg->MCR.int_oe = 1;
uxreg->IER.recv_rdy = 1;
uxreg->IER.line_stat = 1;
uxreg->IER.thr_empty = 1;
PFIC_EnableIRQ(serial_cfg->hw_cfg.serial_irq_interrupt);
break;
}
return EOK;
}
static uint32 SerialDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) {
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
int serial_operation_cmd;
struct SerialDriver *serial_drv = (struct SerialDriver *)drv;
switch (configure_info->configure_cmd) {
case OPE_INT:
ret = SerialInit(serial_drv, configure_info);
break;
case OPE_CFG:
serial_operation_cmd = *(int *)configure_info->private_data;
ret = SerialConfigure(serial_drv, serial_operation_cmd);
break;
default:
break;
}
return ret;
}
static int SerialPutChar(struct SerialHardwareDevice *serial_dev, char ch) {
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
volatile struct uart_registers *uxreg = (struct uart_registers *)serial_cfg->hw_cfg.serial_register_base;
if (uxreg->TFC >= UART_FIFO_SIZE) {
return -1;
}
while (1 != uxreg->LSR.tx_fifo_emp);
uxreg->THR = ch;
return 1;
}
static int SerialGetChar(struct SerialHardwareDevice *serial_dev) {
int ch = -1;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
volatile struct uart_registers *uxreg = (struct uart_registers *)serial_cfg->hw_cfg.serial_register_base;
if (1 == uxreg->LSR.data_rdy) {
/* UART_II_RECV_RDY is cleared by reading RBR */
ch = (uxreg->RFC > 0) ? uxreg->RBR : -1;
}
return ch;
}
static const struct SerialDataCfg data_cfg_init = {
.serial_baud_rate = BAUD_RATE_115200,
.serial_data_bits = DATA_BITS_8,
.serial_stop_bits = STOP_BITS_1,
.serial_parity_mode = PARITY_NONE,
.serial_bit_order = BIT_ORDER_LSB,
.serial_invert_mode = NRZ_NORMAL,
.serial_buffer_size = SERIAL_RB_BUFSZ,
.serial_timeout = WAITING_FOREVER,
};
/*manage the serial device operations*/
static const struct SerialDrvDone drv_done = {
.init = SerialInit,
.configure = SerialConfigure,
};
/*manage the serial device hal operations*/
static struct SerialHwDevDone hwdev_done = {
.put_char = SerialPutChar,
.get_char = SerialGetChar,
};
static int BoardSerialBusInit(struct SerialBus *serial_bus, struct SerialDriver *serial_driver, const char *bus_name,
const char *drv_name) {
x_err_t ret = EOK;
/*Init the serial bus */
ret = SerialBusInit(serial_bus, bus_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialBusInit error %d\n", ret);
return ERROR;
}
/*Init the serial driver*/
ret = SerialDriverInit(serial_driver, drv_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the serial driver to the serial bus*/
ret = SerialDriverAttachToBus(drv_name, bus_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the serial device to the serial bus*/
static int BoardSerialDevBend(struct SerialHardwareDevice *serial_device, void *serial_param, const char *bus_name,
const char *dev_name) {
x_err_t ret = EOK;
ret = SerialDeviceRegister(serial_device, serial_param, dev_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDeviceInit device %s error %d\n", dev_name, ret);
return ERROR;
}
ret = SerialDeviceAttachToBus(dev_name, bus_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDeviceAttachToBus device %s error %d\n", dev_name, ret);
return ERROR;
}
return ret;
}
#ifdef BSP_USING_UART1
struct SerialDriver serial_driver_1;
struct SerialHardwareDevice serial_device_1;
void UART1_IRQHandler(void) __attribute__((interrupt()));
void UART1_IRQHandler(void) {
GET_INT_SP();
x_base level;
level = DisableLocalInterrupt();
isrManager.done->incCounter();
EnableLocalInterrupt(level);
UartIsr(&serial_driver_1, &serial_device_1);
level = DisableLocalInterrupt();
isrManager.done->decCounter();
EnableLocalInterrupt(level);
FREE_INT_SP();
}
#endif
int InitHwUart(void) {
x_err_t ret = EOK;
#ifdef BSP_USING_UART1
static struct SerialBus serial_bus;
memset(&serial_bus, 0, sizeof(struct SerialBus));
memset(&serial_driver_1, 0, sizeof(struct SerialDriver));
memset(&serial_device_1, 0, sizeof(struct SerialHardwareDevice));
static struct SerialCfgParam serial_cfg;
memset(&serial_cfg, 0, sizeof(struct SerialCfgParam));
static struct SerialDevParam serial_dev_param;
memset(&serial_dev_param, 0, sizeof(struct SerialDevParam));
serial_driver_1.drv_done = &drv_done;
serial_driver_1.configure = &SerialDrvConfigure;
serial_device_1.hwdev_done = &hwdev_done;
serial_cfg.data_cfg = data_cfg_init;
serial_cfg.hw_cfg.serial_register_base = (uint32)BA_UART1;
serial_cfg.hw_cfg.serial_irq_interrupt = UART1_IRQn;
serial_driver_1.private_data = (void *)&serial_cfg;
serial_dev_param.serial_work_mode = SIGN_OPER_INT_RX;
serial_device_1.haldev.private_data = (void *)&serial_dev_param;
ret = BoardSerialBusInit(&serial_bus, &serial_driver_1, SERIAL_BUS_NAME_1, SERIAL_DRV_NAME_1);
if (EOK != ret) {
KPrintf("InitHwUart uarths error ret %u\n", ret);
return ERROR;
}
ret = BoardSerialDevBend(&serial_device_1, (void *)&serial_cfg, SERIAL_BUS_NAME_1, SERIAL_1_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("InitHwUart uarths error ret %u\n", ret);
return ERROR;
}
/* Configure the serial port */
GPIOA_SetBits(GPIO_Pin_8);
GPIOA_ModeCfg(GPIO_Pin_7, GPIO_ModeIN_PU_NSMT); // RXD-pull-up input
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_Slowascent_PP_8mA); // TXD-push-pull output
UART1_DefInit();
#endif
return ret;
}

View File

@ -307,6 +307,17 @@ KERNELPATHS += \
-I$(KERNEL_ROOT)/include #
endif
ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/board/ch569w)
KERNELPATHS += \
-I$(KERNEL_ROOT)/arch/risc-v/ch569w \
-I$(KERNEL_ROOT)/arch/risc-v/ch569w/RVMSIS \
-I$(KERNEL_ROOT)/arch/risc-v/ch569w/User \
-I$(BSP_ROOT)/third_party_driver/include \
-I$(BSP_ROOT)/third_party_driver/Peripheral/inc \
-I$(BSP_ROOT)/include \
-I$(KERNEL_ROOT)/include #
endif
ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/board/rv32m1-vega)
KERNELPATHS += \
-I$(KERNEL_ROOT)/arch/risc-v/rv32m1-vega \