first submission

This commit is contained in:
qiyongshuang
2023-02-01 14:19:13 +08:00
parent d534aad004
commit b79c6ac80d
3711 changed files with 745432 additions and 2 deletions
+83
View File
@@ -0,0 +1,83 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : buf.c
* Author : WCH
* Version : V1.0
* Date : 2022/06/30
* 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 "ch32v20x.h"
#include "buf.h"
#ifdef CONFIG_SIMPLE_BUF_DBG
#define SIMPLE_BUF_DBG(...) printf(__VA_ARGS__)
#else
#define SIMPLE_BUF_DBG(...)
#endif
struct simple_buf *simple_buf_create(struct simple_buf *buf,
uint8_t *buf_pool, uint16_t pool_size)
{
buf->data = buf_pool;
buf->len = 0;
buf->size = pool_size;
buf->__buf = buf_pool;
return buf;
}
void *simple_buf_add(struct simple_buf *buf, size_t len)
{
uint8_t *tail = buf->data + buf->len;
SIMPLE_BUF_DBG("buf %p add len %ld\n", buf, len);
if((buf->size - (buf->data - buf->__buf) - buf->len) < len) {
SIMPLE_BUF_DBG("simple_buf_add: no memory\n");
while(1);
}
buf->len += len;
return tail;
}
void *simple_buf_pull(struct simple_buf *buf, size_t len)
{
void *data = buf->data;
SIMPLE_BUF_DBG("buf %p pull len %ld\n", buf, len);
if(buf->len < len) {
SIMPLE_BUF_DBG("simple_buf_pull: no data\n");
while(1);
}
buf->len -= len;
buf->data += len;
return data;
}
void *simple_buf_add_mem(struct simple_buf *buf, const void *mem,
size_t len)
{
SIMPLE_BUF_DBG("buf %p add len %ld\n", buf, len);
return memcpy(simple_buf_add(buf, len), mem, len);
}
uint8_t *simple_buf_add_u8(struct simple_buf *buf, uint8_t val)
{
uint8_t *u8;
SIMPLE_BUF_DBG("buf %p add val 0x%02x\n", buf, val);
u8 = simple_buf_add(buf, 1);
*u8 = val;
return u8;
}
@@ -0,0 +1,74 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/06/16
* 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.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "ch32v20x_it.h"
#include "CONFIG.h"
/*********************************************************************
* LOCAL FUNCTIONS
*/
void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void BB_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void LLE_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*********************************************************************
* @fn NMI_Handler
*
* @brief This function handles NMI exception.
*
* @return None
*/
void NMI_Handler(void)
{
}
/*********************************************************************
* @fn HardFault_Handler
*
* @brief This function handles Hard Fault exception.
*
* @return None
*/
void HardFault_Handler(void)
{
while(1)
{
}
}
/*********************************************************************
* @fn BB_IRQHandler
*
* @brief BB Interrupt for BLE.
*
* @return None
*/
void BB_IRQHandler(void)
{
BB_IRQLibHandler();
}
/*********************************************************************
* @fn LLE_IRQHandler
*
* @brief LLE Interrupt for BLE.
*
* @return None
*/
void LLE_IRQHandler(void)
{
LLE_IRQLibHandler();
}
@@ -0,0 +1,385 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : hci_test.c
* Author : WCH
* Version : V1.0
* Date : 2022/06/30
* 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 "hci_test.h"
#include "config.h"
static uint16_t _opcode;
static uint8_t hci_pool[100];
static struct simple_buf hci_buffer;
struct simple_buf *bt_hci_cmd_complete_create(uint16_t op, uint8_t plen)
{
struct simple_buf *buf;
struct bt_hci_evt_cmd_complete *cc;
struct bt_hci_evt_hdr *hdr;
struct bt_hci_pkt_type *pt;
buf = simple_buf_create(&hci_buffer, hci_pool, sizeof(hci_pool));
pt = simple_buf_add(buf, sizeof(*pt));
pt->type = BT_HCI_PKT_TYPE_EVT;
hdr = simple_buf_add(buf, sizeof(*hdr));
hdr->evt = BT_HCI_EVT_CMD_COMPLETE;
hdr->len = sizeof(*cc) + plen;
cc = simple_buf_add(buf, sizeof(*cc));
cc->ncmd = 1U;
cc->opcode = op;
return buf;
}
void *hci_cmd_complete(struct simple_buf **buf, uint8_t plen)
{
*buf = bt_hci_cmd_complete_create(_opcode, plen);
return simple_buf_add(*buf, plen);
}
struct simple_buf *cmd_complete_status(uint8_t status)
{
struct simple_buf *buf;
struct bt_hci_evt_cc_status *ccst;
buf = bt_hci_cmd_complete_create(_opcode, sizeof(*ccst));
ccst = simple_buf_add(buf, sizeof(*ccst));
ccst->status = status;
return buf;
}
static void reset(struct simple_buf *buf, struct simple_buf **evt)
{
if (buf) {
PRINT("%s:\n", __FUNCTION__);
*evt = cmd_complete_status(0x00);
}
}
static void le_rx_test(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_cp_le_rx_test *cmd = (void *)buf->data;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
PRINT(" rx channel: %#x\n", cmd->rx_ch);
status = API_LE_ReceiverTestCmd((uint8_t *)cmd, BT_HCI_OP_LE_RX_TEST);
*evt = cmd_complete_status(status);
}
/* Modulation_Index feature is not currently supported */
static void le_rx_test_v2(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_cp_le_rx_test_v2 *cmd = (void *)buf->data;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
PRINT(" rx channel: %#x\n", cmd->rx_ch);
PRINT(" phy: ");
switch(cmd->phy) {
case BT_HCI_LE_RX_PHY_1M:
PRINT("1M\n");
break;
case BT_HCI_LE_RX_PHY_2M:
PRINT("2M\n");
break;;
case BT_HCI_LE_RX_PHY_CODED:
PRINT("CODED\n");
break;
default:
PRINT("Invalid\n");
break;
}
PRINT(" mod_index: %#x\n", cmd->mod_index);
status = API_LE_ReceiverTestCmd((uint8_t *)cmd, BT_HCI_OP_LE_RX_TEST_V2);
*evt = cmd_complete_status(status);
}
static void le_tx_test(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_cp_le_tx_test *cmd = (void *)buf->data;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
PRINT(" tx channel: %#x\n", cmd->tx_ch);
PRINT(" test data len: %d\n", cmd->test_data_len);
PRINT(" pkt payload: ");
switch (cmd->pkt_payload) {
case BT_HCI_TEST_PKT_PAYLOAD_PRBS9:
PRINT("PRBS9\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_11110000:
PRINT("11110000\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_10101010:
PRINT("10101010\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_PRBS15:
PRINT("PRBS15\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_11111111:
PRINT("11111111\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_00000000:
PRINT("00000000\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_00001111:
PRINT("00001111\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_01010101:
PRINT("01010101\n");
break;
default:
PRINT("Invalid\n");
break;
}
status =API_LE_TransmitterTestCmd((uint8_t *)cmd, BT_HCI_OP_LE_TX_TEST);
*evt = cmd_complete_status(status);
}
static void le_tx_test_v2(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_cp_le_tx_test_v2 *cmd = (void *)buf->data;
uint8_t status;
PRINT("%s:", __FUNCTION__);
PRINT(" tx channel: %#x\n", cmd->tx_ch);
PRINT(" test data len: %d\n", cmd->test_data_len);
PRINT(" pkt payload: ");
switch (cmd->pkt_payload) {
case BT_HCI_TEST_PKT_PAYLOAD_PRBS9:
PRINT("PRBS9\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_11110000:
PRINT("11110000\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_10101010:
PRINT("10101010\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_PRBS15:
PRINT("PRBS15\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_11111111:
PRINT("11111111\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_00000000:
PRINT("00000000\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_00001111:
PRINT("00001111\n");
break;
case BT_HCI_TEST_PKT_PAYLOAD_01010101:
PRINT("01010101\n");
break;
default:
PRINT("Invalid\n");
break;
}
PRINT(" phy: ");
switch(cmd->phy) {
case BT_HCI_LE_TX_PHY_1M:
PRINT("1M\n");
break;
case BT_HCI_LE_TX_PHY_2M:
PRINT("2M\n");
break;;
case BT_HCI_LE_TX_PHY_CODED_S8:
PRINT("CODED_S8\n");
break;
case BT_HCI_LE_TX_PHY_CODED_S2:
PRINT("CODED_S2\n");
break;
default:
PRINT("Invalid\n");
break;
}
status = API_LE_TransmitterTestCmd((uint8_t *)cmd, BT_HCI_OP_LE_TX_TEST_V2);
*evt = cmd_complete_status(status);
}
static void le_test_end(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_rp_le_test_end *rp;
uint16_t rx_pkt_count;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
LL_TestEnd((uint8_t *)&rx_pkt_count);
status = API_LE_TestEndCmd();
PRINT(" status: %#x\n", status);
PRINT(" pkt count: %ld\n", rx_pkt_count);
rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = status;
rp->rx_pkt_count = rx_pkt_count;
}
static void le_set_txpower(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_set_txpower *tp = (void *)buf->data;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
PRINT(" tx power: %#x\n", tp->tx_power);
status = LL_SetTxPowerLevel(tp->tx_power);
*evt = cmd_complete_status(status);
}
static void le_set_xt32m_tune(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_xt32m_tune *xt = (void *)buf->data;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
PRINT(" xt32m tune: %#x\n", xt->xt32m_tune);
if(xt->xt32m_tune > 7) {
*evt = cmd_complete_status(0x12); //Invalid hci comd param
}
OSC->HSE_CAL_CTRL &= ~(0x07<<28);
OSC->HSE_CAL_CTRL |= xt->xt32m_tune<<28;
*evt = cmd_complete_status(0x00);
}
static void le_set_single_carrier(struct simple_buf *buf, struct simple_buf **evt)
{
struct bt_hci_single_carrier *sc = (void *)buf->data;
uint8_t status;
PRINT("%s:\n", __FUNCTION__);
PRINT(" single carrier: %#x\n", sc->single_carrier);
status = LL_SingleChannel(sc->single_carrier);
*evt = cmd_complete_status(status);
}
static int ctrl_bb_cmd_handle(uint16_t ocf, struct simple_buf *cmd,
struct simple_buf **evt)
{
switch (ocf) {
case BT_OCF(BT_HCI_OP_RESET):
reset(cmd, evt);
break;
default:
return -1;
}
return 0;
}
static int controller_cmd_handle(uint16_t ocf, struct simple_buf *cmd,
struct simple_buf **evt)
{
switch (ocf) {
case BT_OCF(BT_HCI_OP_LE_RX_TEST):
le_rx_test(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_TX_TEST):
le_tx_test(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_RX_TEST_V2):
le_rx_test_v2(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_TX_TEST_V2):
le_tx_test_v2(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_TEST_END):
le_test_end(cmd, evt);
break;
default:
return -1;
}
return 0;
}
static int hci_vendor_cmd_handle(uint16_t ocf, struct simple_buf *cmd,
struct simple_buf **evt)
{
switch (ocf)
{
case BT_OCF(BT_HCI_SET_TXPOWER):
le_set_txpower(cmd, evt);
break;
case BT_OCF(BT_HCI_XT32M_TUNE):
le_set_xt32m_tune(cmd, evt);
break;
case BT_OCF(BT_HCI_SINGLE_CARRIER):
le_set_single_carrier(cmd, evt);
break;
default:
return -1;
}
return 0;
}
struct simple_buf *hci_cmd_handle(struct simple_buf *cmd)
{
struct bt_hci_pkt_type *pt;
struct bt_hci_cmd_hdr *chdr;
struct simple_buf *evt = NULL;
uint16_t ocf;
int err;
pt = simple_buf_pull(cmd, sizeof(*pt));
if(pt->type != BT_HCI_PKT_TYPE_CMD) {
PRINT("Invalid HCI CMD packet type\n");
return NULL;
}
if (cmd->len < sizeof(*chdr)) {
PRINT("No HCI Command header\n");
return NULL;
}
chdr = simple_buf_pull(cmd, sizeof(*chdr));
if (cmd->len < chdr->param_len) {
PRINT("Invalid HCI CMD packet length\n");
return NULL;
}
/* store in a global for later CC/CS event creation */
_opcode = chdr->opcode;
ocf = BT_OCF(_opcode);
switch (BT_OGF(_opcode)) {
case BT_OGF_BASEBAND:
err = ctrl_bb_cmd_handle(ocf, cmd, &evt);
break;
case BT_OGF_LE:
err = controller_cmd_handle(ocf, cmd, &evt);
break;
case BT_OGF_VS:
err = hci_vendor_cmd_handle(ocf, cmd, &evt);
break;
default:
err = -1;
break;
}
return evt;
}
@@ -0,0 +1,224 @@
/*
* Copyright (c) 1997-2015, Wind River Systems, Inc.
* Copyright (c) 2021 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_SYS_ATOMIC_H_
#define ZEPHYR_INCLUDE_SYS_ATOMIC_H_
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int atomic_t;
typedef atomic_t atomic_val_t;
typedef void *atomic_ptr_t;
typedef atomic_ptr_t atomic_ptr_val_t;
#include <atomic_builtin.h>
/* Portable higher-level utilities: */
/**
* @defgroup atomic_apis Atomic Services APIs
* @ingroup kernel_apis
* @{
*/
/**
* @brief Initialize an atomic variable.
*
* This macro can be used to initialize an atomic variable. For example,
* @code atomic_t my_var = ATOMIC_INIT(75); @endcode
*
* @param i Value to assign to atomic variable.
*/
#define ATOMIC_INIT(i) (i)
/**
* @brief Initialize an atomic pointer variable.
*
* This macro can be used to initialize an atomic pointer variable. For
* example,
* @code atomic_ptr_t my_ptr = ATOMIC_PTR_INIT(&data); @endcode
*
* @param p Pointer value to assign to atomic pointer variable.
*/
#define ATOMIC_PTR_INIT(p) (p)
/**
* @cond INTERNAL_HIDDEN
*/
#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
#define ATOMIC_MASK(bit) (1U << ((uint32_t)(bit) & (ATOMIC_BITS - 1U)))
#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
/**
* INTERNAL_HIDDEN @endcond
*/
/**
* @brief This macro computes the number of atomic variables necessary to
* represent a bitmap with @a num_bits.
*
* @param num_bits Number of bits.
*/
#define ATOMIC_BITMAP_SIZE(num_bits) (1 + ((num_bits) - 1) / ATOMIC_BITS)
/**
* @brief Define an array of atomic variables.
*
* This macro defines an array of atomic variables containing at least
* @a num_bits bits.
*
* @note
* If used from file scope, the bits of the array are initialized to zero;
* if used from within a function, the bits are left uninitialized.
*
* @cond INTERNAL_HIDDEN
* @note
* This macro should be replicated in the PREDEFINED field of the documentation
* Doxyfile.
* @endcond
*
* @param name Name of array of atomic variables.
* @param num_bits Number of bits needed.
*/
#define ATOMIC_DEFINE(name, num_bits) \
atomic_t name[ATOMIC_BITMAP_SIZE(num_bits)]
/**
* @brief Atomically test a bit.
*
* This routine tests whether bit number @a bit of @a target is set or not.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return true if the bit was set, false if it wasn't.
*/
static inline bool atomic_test_bit(const atomic_t *target, int bit)
{
atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
return (1 & (val >> (bit & (ATOMIC_BITS - 1)))) != 0;
}
/**
* @brief Atomically test and clear a bit.
*
* Atomically clear bit number @a bit of @a target and return its old value.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return true if the bit was set, false if it wasn't.
*/
static inline bool atomic_test_and_clear_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
atomic_val_t old;
old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
return (old & mask) != 0;
}
/**
* @brief Atomically set a bit.
*
* Atomically set bit number @a bit of @a target and return its old value.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return true if the bit was set, false if it wasn't.
*/
static inline bool atomic_test_and_set_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
atomic_val_t old;
old = atomic_or(ATOMIC_ELEM(target, bit), mask);
return (old & mask) != 0;
}
/**
* @brief Atomically clear a bit.
*
* Atomically clear bit number @a bit of @a target.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return N/A
*/
static inline void atomic_clear_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
}
/**
* @brief Atomically set a bit.
*
* Atomically set bit number @a bit of @a target.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return N/A
*/
static inline void atomic_set_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
}
/**
* @brief Atomically set a bit to a given value.
*
* Atomically set bit number @a bit of @a target to value @a val.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
* @param val true for 1, false for 0.
*
* @return N/A
*/
static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
{
atomic_val_t mask = ATOMIC_MASK(bit);
if (val) {
(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
} else {
(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
}
}
/**
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* ZEPHYR_INCLUDE_SYS_ATOMIC_H_ */
@@ -0,0 +1,303 @@
/* atomic operations */
/*
* Copyright (c) 1997-2015, Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_SYS_ATOMIC_BUILTIN_H_
#define ZEPHYR_INCLUDE_SYS_ATOMIC_BUILTIN_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Included from <atomic.h> */
/**
* @addtogroup atomic_apis Atomic Services APIs
* @ingroup kernel_apis
* @{
*/
/**
* @brief Atomic compare-and-set.
*
* This routine performs an atomic compare-and-set on @a target. If the current
* value of @a target equals @a old_value, @a target is set to @a new_value.
* If the current value of @a target does not equal @a old_value, @a target
* is left unchanged.
*
* @param target Address of atomic variable.
* @param old_value Original value to compare against.
* @param new_value New value to store.
* @return true if @a new_value is written, false otherwise.
*/
static inline bool atomic_cas(atomic_t *target, atomic_val_t old_value,
atomic_val_t new_value)
{
return __atomic_compare_exchange_n(target, &old_value, new_value,
0, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
}
/**
* @brief Atomic compare-and-set with pointer values
*
* This routine performs an atomic compare-and-set on @a target. If the current
* value of @a target equals @a old_value, @a target is set to @a new_value.
* If the current value of @a target does not equal @a old_value, @a target
* is left unchanged.
*
* @param target Address of atomic variable.
* @param old_value Original value to compare against.
* @param new_value New value to store.
* @return true if @a new_value is written, false otherwise.
*/
static inline bool atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value,
atomic_ptr_val_t new_value)
{
return __atomic_compare_exchange_n(target, &old_value, new_value,
0, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic addition.
*
* This routine performs an atomic addition on @a target.
*
* @param target Address of atomic variable.
* @param value Value to add.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic subtraction.
*
* This routine performs an atomic subtraction on @a target.
*
* @param target Address of atomic variable.
* @param value Value to subtract.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic increment.
*
* This routine performs an atomic increment by 1 on @a target.
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_inc(atomic_t *target)
{
return atomic_add(target, 1);
}
/**
*
* @brief Atomic decrement.
*
* This routine performs an atomic decrement by 1 on @a target.
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_dec(atomic_t *target)
{
return atomic_sub(target, 1);
}
/**
*
* @brief Atomic get.
*
* This routine performs an atomic read on @a target.
*
* @param target Address of atomic variable.
*
* @return Value of @a target.
*/
static inline atomic_val_t atomic_get(const atomic_t *target)
{
return __atomic_load_n(target, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic get a pointer value
*
* This routine performs an atomic read on @a target.
*
* @param target Address of pointer variable.
*
* @return Value of @a target.
*/
static inline atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target)
{
return __atomic_load_n(target, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic get-and-set.
*
* This routine atomically sets @a target to @a value and returns
* the previous value of @a target.
*
* @param target Address of atomic variable.
* @param value Value to write to @a target.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
{
/* This builtin, as described by Intel, is not a traditional
* test-and-set operation, but rather an atomic exchange operation. It
* writes value into *ptr, and returns the previous contents of *ptr.
*/
return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic get-and-set for pointer values
*
* This routine atomically sets @a target to @a value and returns
* the previous value of @a target.
*
* @param target Address of atomic variable.
* @param value Value to write to @a target.
*
* @return Previous value of @a target.
*/
static inline atomic_ptr_val_t atomic_ptr_set(atomic_ptr_t *target, atomic_ptr_val_t value)
{
return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic clear.
*
* This routine atomically sets @a target to zero and returns its previous
* value. (Hence, it is equivalent to atomic_set(target, 0).)
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_clear(atomic_t *target)
{
return atomic_set(target, 0);
}
/**
*
* @brief Atomic clear of a pointer value
*
* This routine atomically sets @a target to zero and returns its previous
* value. (Hence, it is equivalent to atomic_set(target, 0).)
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_ptr_val_t atomic_ptr_clear(atomic_ptr_t *target)
{
return atomic_ptr_set(target, NULL);
}
/**
*
* @brief Atomic bitwise inclusive OR.
*
* This routine atomically sets @a target to the bitwise inclusive OR of
* @a target and @a value.
*
* @param target Address of atomic variable.
* @param value Value to OR.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic bitwise exclusive OR (XOR).
*
* This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
* @a target and @a value.
*
* @param target Address of atomic variable.
* @param value Value to XOR
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic bitwise AND.
*
* This routine atomically sets @a target to the bitwise AND of @a target
* and @a value.
*
* @param target Address of atomic variable.
* @param value Value to AND.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic bitwise NAND.
*
* This routine atomically sets @a target to the bitwise NAND of @a target
* and @a value. (This operation is equivalent to target = ~(target & value).)
*
* @param target Address of atomic variable.
* @param value Value to NAND.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_SYS_ATOMIC_BUILTIN_H_ */
@@ -0,0 +1,103 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : buf.h
* Author : WCH
* Version : V1.0
* Date : 2022/06/30
* 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 BLE_DIRECTTEST_APP_INCLUDE_BUF_H
#define BLE_DIRECTTEST_APP_INCLUDE_BUF_H
#include <stdint.h>
#include <stddef.h>
#include <string.h>
struct simple_buf {
/** Pointer to the start of data in the buffer. */
uint8_t *data;
/**
* Length of the data behind the data pointer.
*
*/
uint16_t len;
/** Amount of data that simple buf can store. */
uint16_t size;
/** Start of the data storage. Not to be accessed directly
* (the data pointer should be used instead).
*/
uint8_t *__buf;
};
/**
* @brief create a simple_buf object.
*
* @param buf simple_buf object
* @param buf_pool simple_buf buffer
* @param pool_size simple_buf size
*/
struct simple_buf *simple_buf_create(struct simple_buf *buf,
uint8_t *buf_pool, uint16_t pool_size);
/**
* @brief Prepare data to be added at the end of the buffer
*
* Increments the data length of a buffer to account for more data
* at the end.
*
* @param buf Buffer to update.
* @param len Number of bytes to increment the length with.
*
* @return The original tail of the buffer.
*/
void *simple_buf_add(struct simple_buf *buf, size_t len);
/**
* @brief Prepare data to be added to the start of the buffer
*
* Modifies the data pointer and buffer length to account for more data
* in the beginning of the buffer.
*
* @param buf Buffer to update.
* @param len Number of bytes to add to the beginning.
*
* @return The new beginning of the buffer data.
*/
void *simple_buf_pull(struct simple_buf *buf, size_t len);
/**
* @brief Copy given number of bytes from memory to the end of the buffer
*
* Increments the data length of the buffer to account for more data at the
* end.
*
* @param buf Buffer to update.
* @param mem Location of data to be added.
* @param len Length of data to be added
*
* @return The original tail of the buffer.
*/
void *simple_buf_add_mem(struct simple_buf *buf, const void *mem,
size_t len);
/**
* @brief Add (8-bit) byte at the end of the buffer
*
* Increments the data length of the buffer to account for more data at the
* end.
*
* @param buf Buffer to update.
* @param val byte value to be added.
*
* @return Pointer to the value added
*/
uint8_t *simple_buf_add_u8(struct simple_buf *buf, uint8_t val);
#endif /* BLE_DIRECTTEST_APP_INCLUDE_BUF_H */
@@ -0,0 +1,37 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_conf.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/06/16
* Description : Library configuration file.
*********************************************************************************
* 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 __CH32V20x_CONF_H
#define __CH32V20x_CONF_H
#include "ch32v20x_adc.h"
#include "ch32v20x_bkp.h"
#include "ch32v20x_can.h"
#include "ch32v20x_crc.h"
#include "ch32v20x_dbgmcu.h"
#include "ch32v20x_dma.h"
#include "ch32v20x_exti.h"
#include "ch32v20x_flash.h"
#include "ch32v20x_gpio.h"
#include "ch32v20x_i2c.h"
#include "ch32v20x_iwdg.h"
#include "ch32v20x_pwr.h"
#include "ch32v20x_rcc.h"
#include "ch32v20x_rtc.h"
#include "ch32v20x_spi.h"
#include "ch32v20x_tim.h"
#include "ch32v20x_usart.h"
#include "ch32v20x_wwdg.h"
#include "ch32v20x_it.h"
#include "ch32v20x_misc.h"
#endif /* __CH32V20x_CONF_H */
@@ -0,0 +1,18 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v20x_it.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/06/16
* 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 __CH32V20x_IT_H
#define __CH32V20x_IT_H
#include "debug.h"
#endif /* __CH32V20x_IT_H */
@@ -0,0 +1,150 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : hci_test.h
* Author : WCH
* Version : V1.0
* Date : 2022/06/29
* 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 BLE_DIRECTTEST_APP_INCLUDE_HCI_TEST_H
#define BLE_DIRECTTEST_APP_INCLUDE_HCI_TEST_H
#include <stdint.h>
#include "buf.h"
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif
#define BT_HCI_LE_RX_PHY_1M 0x01
#define BT_HCI_LE_RX_PHY_2M 0x02
#define BT_HCI_LE_RX_PHY_CODED 0x03
#define BT_HCI_LE_TX_PHY_1M 0x01
#define BT_HCI_LE_TX_PHY_2M 0x02
#define BT_HCI_LE_TX_PHY_CODED_S8 0x03
#define BT_HCI_LE_TX_PHY_CODED_S2 0x04
#define BT_HCI_TEST_PKT_PAYLOAD_PRBS9 0x00
#define BT_HCI_TEST_PKT_PAYLOAD_11110000 0x01
#define BT_HCI_TEST_PKT_PAYLOAD_10101010 0x02
#define BT_HCI_TEST_PKT_PAYLOAD_PRBS15 0x03
#define BT_HCI_TEST_PKT_PAYLOAD_11111111 0x04
#define BT_HCI_TEST_PKT_PAYLOAD_00000000 0x05
#define BT_HCI_TEST_PKT_PAYLOAD_00001111 0x06
#define BT_HCI_TEST_PKT_PAYLOAD_01010101 0x07
struct bt_hci_pkt_type {
uint8_t type;
}__packed;
struct bt_hci_evt_hdr {
uint8_t evt;
uint8_t len;
} __packed;
struct bt_hci_cmd_hdr {
uint16_t opcode;
uint8_t param_len;
} __packed;
/* HCI packet type */
#define BT_HCI_PKT_TYPE_CMD 0x01
#define BT_HCI_PKT_TYPE_ACL 0x02
#define BT_HCI_PKT_TYPE_SYNC 0x03
#define BT_HCI_PKT_TYPE_EVT 0x04
#define BT_HCI_PKT_TYPE_ISO 0x05
/* HCI BR/EDR link types */
#define BT_HCI_SCO 0x00
#define BT_HCI_ACL 0x01
#define BT_HCI_ESCO 0x02
/* OpCode Group Fields */
#define BT_OGF_LINK_CTRL 0x01
#define BT_OGF_BASEBAND 0x03
#define BT_OGF_INFO 0x04
#define BT_OGF_STATUS 0x05
#define BT_OGF_LE 0x08
#define BT_OGF_VS 0x3f
/* Construct OpCode from OGF and OCF */
#define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10))
/* Invalid opcode */
#define BT_OP_NOP 0x0000
/* Obtain OGF from OpCode */
#define BT_OGF(opcode) (((opcode) >> 10) & ((1<<6)- 1U))
/* Obtain OCF from OpCode */
#define BT_OCF(opcode) ((opcode) & ((1<<10) - 1U))
#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003)
#define BT_HCI_OP_LE_TEST_END BT_OP(BT_OGF_LE, 0x001f)
struct bt_hci_rp_le_test_end {
uint8_t status;
uint16_t rx_pkt_count;
} __packed;
#define BT_HCI_OP_LE_RX_TEST BT_OP(BT_OGF_LE, 0x001d)
struct bt_hci_cp_le_rx_test {
uint8_t rx_ch;
} __packed;
#define BT_HCI_OP_LE_RX_TEST_V2 BT_OP(BT_OGF_LE, 0x0033)
struct bt_hci_cp_le_rx_test_v2 {
uint8_t rx_ch;
uint8_t phy;
/* ATTENTION: Modulation_Index feature is not currently supported */
uint8_t mod_index;
} __packed;
#define BT_HCI_OP_LE_TX_TEST BT_OP(BT_OGF_LE, 0x001e)
struct bt_hci_cp_le_tx_test {
uint8_t tx_ch;
uint8_t test_data_len;
uint8_t pkt_payload;
} __packed;
#define BT_HCI_OP_LE_TX_TEST_V2 BT_OP(BT_OGF_LE, 0x0034)
struct bt_hci_cp_le_tx_test_v2 {
uint8_t tx_ch;
uint8_t test_data_len;
uint8_t pkt_payload;
uint8_t phy;
} __packed;
#define BT_HCI_EVT_CMD_COMPLETE 0x0e
struct bt_hci_evt_cmd_complete {
uint8_t ncmd;
uint16_t opcode;
} __packed;
struct bt_hci_evt_cc_status {
uint8_t status;
} __packed;
/*vender cmds*/
#define BT_HCI_SET_TXPOWER BT_OP(BT_OGF_VS, 0x0301)
struct bt_hci_set_txpower {
uint8_t tx_power;
} __packed;
#define BT_HCI_XT32M_TUNE BT_OP(BT_OGF_VS, 0x0302)
struct bt_hci_xt32m_tune {
uint8_t xt32m_tune;
} __packed;
#define BT_HCI_SINGLE_CARRIER BT_OP(BT_OGF_VS, 0x0303)
struct bt_hci_single_carrier {
uint8_t single_carrier;
} __packed;
struct simple_buf *hci_cmd_handle(struct simple_buf *cmd);
#endif /* BLE_DIRECTTEST_APP_INCLUDE_HCI_TEST_H */
@@ -0,0 +1,31 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v20x.h
* Author : WCH
* Version : V1.0.0
* Date : 2022/06/16
* Description : CH32V20x Device Peripheral Access Layer System Header File.
*********************************************************************************
* 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 __SYSTEM_ch32v20x_H
#define __SYSTEM_ch32v20x_H
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */
/* System_Exported_Functions */
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
#ifdef __cplusplus
}
#endif
#endif /*__CH32V20x_SYSTEM_H */
@@ -0,0 +1,22 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : test_dtm.h
* Author : WCH
* Version : V1.0
* Date : 2022/06/29
* 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 BLE_DIRECTTEST_APP_INCLUDE_TEST_DTM_H
#define BLE_DIRECTTEST_APP_INCLUDE_TEST_DTM_H
#include "hci_test.h"
extern tmosTaskID test_taskid;
void test_dtm_init(void);
#endif /* BLE_DIRECTTEST_APP_INCLUDE_TEST_DTM_H */
@@ -0,0 +1,34 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : uart.h
* Author : WCH
* Version : V1.0
* Date : 2022/06/30
* 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 BLE_DIRECTTEST_APP_INCLUDE_UART_H
#define BLE_DIRECTTEST_APP_INCLUDE_UART_H
#include "config.h"
#include "buf.h"
#define UART_PROCESS_EVT 1
/*process events*/
#define UART_RECEIVE_POLL_EVT (1<<0)
struct uart_process_msg {
tmos_event_hdr_t hdr;
uint8_t *data;
};
int uart_send(struct simple_buf *buf);
int uart_start_receiving(void);
void uart_task_init(void);
#endif /* BLE_DIRECTTEST_APP_INCLUDE_UART_H */
+68
View File
@@ -0,0 +1,68 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0
* Date : 2020/08/06
* Description : Direct test mode
*********************************************************************************
* 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.
*******************************************************************************/
/******************************************************************************/
/* Header file contains */
#include "CONFIG.h"
#include "HAL.h"
#include "test_dtm.h"
#include "uart.h"
/*********************************************************************
* GLOBAL TYPEDEFS
*/
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
const uint8_t MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
#endif
/*********************************************************************
* @fn Main_Circulation
*
* @brief Main loop
*
* @return none
*/
__attribute__((section(".highcode")))
__attribute__((noinline))
void Main_Circulation(void)
{
while(1)
{
TMOS_SystemProcess();
}
}
/*********************************************************************
* @fn main
*
* @brief Main function
*
* @return none
*/
int main(void)
{
Delay_Init();
#ifdef DEBUG
USART_Printf_Init( 115200 );
#endif
PRINT("%s\n", VER_LIB);
WCHBLE_Init();
HAL_Init();
uart_task_init();
test_dtm_init();
GAPRole_BroadcasterInit();
Main_Circulation();
}
/******************************** endfile @ main ******************************/
@@ -0,0 +1,989 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : system_ch32v20x.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : CH32V20x Device Peripheral Access Layer System Source File.
* For HSE = 32Mhz (CH32V208x/CH32V203RBT6)
* For HSE = 8Mhz (other CH32V203x)
*********************************************************************************
* 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 "ch32v20x.h"
/*
* Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after
* reset the HSI is used as SYSCLK source).
* If none of the define below is enabled, the HSI is used as System clock source.
*/
//#define SYSCLK_FREQ_HSE HSE_VALUE
//#define SYSCLK_FREQ_48MHz_HSE 48000000
//#define SYSCLK_FREQ_56MHz_HSE 56000000
//#define SYSCLK_FREQ_72MHz_HSE 72000000
#define SYSCLK_FREQ_96MHz_HSE 96000000
//#define SYSCLK_FREQ_120MHz_HSE 120000000
//#define SYSCLK_FREQ_144MHz_HSE 144000000
//#define SYSCLK_FREQ_HSI HSI_VALUE
//#define SYSCLK_FREQ_48MHz_HSI 48000000
//#define SYSCLK_FREQ_56MHz_HSI 56000000
//#define SYSCLK_FREQ_72MHz_HSI 72000000
//#define SYSCLK_FREQ_96MHz_HSI 96000000
//#define SYSCLK_FREQ_120MHz_HSI 120000000
//#define SYSCLK_FREQ_144MHz_HSI 144000000
/* Clock Definitions */
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSE; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_96MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_120MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_120MHz_HSI; /* System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_144MHz_HSI
uint32_t SystemCoreClock = SYSCLK_FREQ_144MHz_HSI; /* System Clock Frequency (Core Clock) */
#else
uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */
#endif
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/* system_private_function_proto_types */
static void SetSysClock(void);
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSE
static void SetSysClockTo48_HSE( void );
#elif defined SYSCLK_FREQ_56MHz_HSE
static void SetSysClockTo56_HSE( void );
#elif defined SYSCLK_FREQ_72MHz_HSE
static void SetSysClockTo72_HSE( void );
#elif defined SYSCLK_FREQ_96MHz_HSE
static void SetSysClockTo96_HSE( void );
#elif defined SYSCLK_FREQ_120MHz_HSE
static void SetSysClockTo120_HSE( void );
#elif defined SYSCLK_FREQ_144MHz_HSE
static void SetSysClockTo144_HSE( void );
#elif defined SYSCLK_FREQ_48MHz_HSI
static void SetSysClockTo48_HSI( void );
#elif defined SYSCLK_FREQ_56MHz_HSI
static void SetSysClockTo56_HSI( void );
#elif defined SYSCLK_FREQ_72MHz_HSI
static void SetSysClockTo72_HSI( void );
#elif defined SYSCLK_FREQ_96MHz_HSI
static void SetSysClockTo96_HSI( void );
#elif defined SYSCLK_FREQ_120MHz_HSI
static void SetSysClockTo120_HSI( void );
#elif defined SYSCLK_FREQ_144MHz_HSI
static void SetSysClockTo144_HSI( void );
#endif
/*********************************************************************
* @fn SystemInit
*
* @brief Setup the microcontroller system Initialize the Embedded Flash Interface,
* the PLL and update the SystemCoreClock variable.
*
* @return none
*/
void SystemInit (void)
{
RCC->CTLR |= (uint32_t)0x00000001;
RCC->CFGR0 &= (uint32_t)0xF8FF0000;
RCC->CTLR &= (uint32_t)0xFEF6FFFF;
RCC->CTLR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR0 &= (uint32_t)0xFF80FFFF;
RCC->INTR = 0x009F0000;
SetSysClock();
}
/*********************************************************************
* @fn SystemCoreClockUpdate
*
* @brief Update SystemCoreClock variable according to Clock Register Values.
*
* @return none
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
tmp = RCC->CFGR0 & RCC_SWS;
switch (tmp)
{
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
case 0x04:
SystemCoreClock = HSE_VALUE;
break;
case 0x08:
pllmull = RCC->CFGR0 & RCC_PLLMULL;
pllsource = RCC->CFGR0 & RCC_PLLSRC;
pllmull = ( pllmull >> 18) + 2;
if(pllmull == 17) pllmull = 18;
if (pllsource == 0x00)
{
if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){
SystemCoreClock = HSI_VALUE * pllmull;
}
else{
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
}
else
{
#if defined (CH32V20x_D8W)
if((RCC->CFGR0 & (3<<22)) == (3<<22))
{
SystemCoreClock = ((HSE_VALUE>>1)) * pllmull;
}
else
#endif
if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET)
{
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull;
#else
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
#endif
}
else
{
#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
SystemCoreClock = (HSE_VALUE>>2) * pllmull;
#else
SystemCoreClock = HSE_VALUE * pllmull;
#endif
}
}
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)];
SystemCoreClock >>= tmp;
}
/*********************************************************************
* @fn SetSysClock
*
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_48MHz_HSE
SetSysClockTo48_HSE();
#elif defined SYSCLK_FREQ_56MHz_HSE
SetSysClockTo56_HSE();
#elif defined SYSCLK_FREQ_72MHz_HSE
SetSysClockTo72_HSE();
#elif defined SYSCLK_FREQ_96MHz_HSE
SetSysClockTo96_HSE();
#elif defined SYSCLK_FREQ_120MHz_HSE
SetSysClockTo120_HSE();
#elif defined SYSCLK_FREQ_144MHz_HSE
SetSysClockTo144_HSE();
#elif defined SYSCLK_FREQ_48MHz_HSI
SetSysClockTo48_HSI();
#elif defined SYSCLK_FREQ_56MHz_HSI
SetSysClockTo56_HSI();
#elif defined SYSCLK_FREQ_72MHz_HSI
SetSysClockTo72_HSI();
#elif defined SYSCLK_FREQ_96MHz_HSI
SetSysClockTo96_HSI();
#elif defined SYSCLK_FREQ_120MHz_HSI
SetSysClockTo120_HSI();
#elif defined SYSCLK_FREQ_144MHz_HSI
SetSysClockTo144_HSI();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
* source (default after reset)
*/
}
#ifdef SYSCLK_FREQ_HSE
/*********************************************************************
* @fn SetSysClockToHSE
*
* @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockToHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1;
/* Select HSE as system clock source
* CH32V20x_D6 (HSE=8MHZ)
* CH32V20x_D8 (HSE=32MHZ)
* CH32V20x_D8W (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSE
/*********************************************************************
* @fn SetSysClockTo48_HSE
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 6 = 48 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 6 = 48 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_56MHz_HSE
/*********************************************************************
* @fn SetSysClockTo56_HSE
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 7 = 56 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 7 = 56 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL7);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_72MHz_HSE
/*********************************************************************
* @fn SetSysClockTo72_HSE
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 9 = 72 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 9 = 72 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL9);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_96MHz_HSE
/*********************************************************************
* @fn SetSysClockTo96_HSE
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_120MHz_HSE
/*********************************************************************
* @fn SetSysClockTo120_HSE
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if(HSEStatus == (uint32_t)0x01)
{
#if defined (CH32V20x_D8W)
RCC->CFGR0 |= (uint32_t)(3<<22);
/* HCLK = SYSCLK/2 */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
#else
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
#endif
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 15 = 120 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 15 = 120 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/2 * 15 = 240 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL15);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_144MHz_HSE
/*********************************************************************
* @fn SetSysClockTo144_HSE
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CTLR |= ((uint32_t)RCC_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CTLR & RCC_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CTLR & RCC_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 18 = 144 MHz (HSE=8MHZ)
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 18 = 144 MHz (HSE=32MHZ)
*/
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL18);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
else
{
/*
* If HSE fails to start-up, the application will have wrong clock
* configuration. User can add here some code to deal with this error
*/
}
}
#elif defined SYSCLK_FREQ_48MHz_HSI
/*********************************************************************
* @fn SetSysClockTo48_HSI
*
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo48_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_56MHz_HSI
/*********************************************************************
* @fn SetSysClockTo56_HSI
*
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo56_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 7 = 48 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_72MHz_HSI
/*********************************************************************
* @fn SetSysClockTo72_HSI
*
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo72_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_96MHz_HSI
/*********************************************************************
* @fn SetSysClockTo96_HSI
*
* @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo96_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 12 = 96 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL12);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_120MHz_HSI
/*********************************************************************
* @fn SetSysClockTo120_HSI
*
* @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo120_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 15 = 120 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE |
RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL15);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#elif defined SYSCLK_FREQ_144MHz_HSI
/*********************************************************************
* @fn SetSysClockTo144_HSI
*
* @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
*
* @return none
*/
static void SetSysClockTo144_HSI(void)
{
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
/* HCLK = SYSCLK */
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 18 = 144 MHz */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL));
RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL18);
/* Enable PLL */
RCC->CTLR |= RCC_PLLON;
/* Wait till PLL is ready */
while((RCC->CTLR & RCC_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08)
{
}
}
#endif
@@ -0,0 +1,83 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : test_dtm.c
* Author : WCH
* Version : V1.0
* Date : 2022/06/29
* 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 "config.h"
#include "test_dtm.h"
#include "uart.h"
tmosTaskID test_taskid = INVALID_TASK_ID;
/*********************************************************************
* @fn test_dtm_process_msg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void test_dtm_process_msg(tmos_event_hdr_t *pMsg) {
switch (pMsg->event) {
case UART_PROCESS_EVT:{
struct simple_buf *evt = NULL;
struct uart_process_msg *msg = \
(struct uart_process_msg *)pMsg;
evt = hci_cmd_handle((struct simple_buf*)msg->data);
if(evt)
uart_send(evt);
uart_start_receiving();
}
break;
default:
break;
}
}
/*********************************************************************
* @fn test_dtm_processevent
*
* @brief process handle
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed
*/
tmosEvents test_dtm_processevent(tmosTaskID task_id, tmosEvents events)
{
uint8_t *msgPtr;
if(events & SYS_EVENT_MSG)
{ // 处理HAL层消息,调用tmos_msg_receive读取消息,处理完成后删除消息。
msgPtr = tmos_msg_receive(task_id);
if(msgPtr)
{
test_dtm_process_msg((tmos_event_hdr_t *)msgPtr);
/* De-allocate */
tmos_msg_deallocate(msgPtr);
}
return (events ^ SYS_EVENT_MSG);
}
return 0;
}
void test_dtm_init(void)
{
test_taskid = TMOS_ProcessEventRegister(test_dtm_processevent);
}
+205
View File
@@ -0,0 +1,205 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : uart.c
* Author : WCH
* Version : V1.0
* Date : 2022/06/30
* 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 "config.h"
#include "uart.h"
#include "atomic.h"
#include "test_dtm.h"
static tmosTaskID uart_taskid;
static uint8_t rx_buf[100];
static struct simple_buf *uart_buf = NULL;
static struct simple_buf uart_buffer;
enum uart_status {
UART_STATUS_IDLE,
UART_STATUS_RCVING,
UART_STATUS_RCV_END,
UART_STATUS_SENDING,
UART_STATUS_NUM,
};
atomic_t uart_flag;
void uart_buffer_create(struct simple_buf **buf)
{
*buf = simple_buf_create(&uart_buffer, rx_buf, sizeof(rx_buf));
}
int uart_start_receiving(void)
{
PRINT("uart2 reeciving\n");
atomic_set(&uart_flag, UART_STATUS_RCVING);
uart_buffer_create(&uart_buf);
USART_Cmd(USART2, ENABLE);
return 0;
}
void uart2_send_data(uint8_t *data, uint16_t len)
{
for(int i = 0; i < len; i++) {
USART_SendData(USART2, data[i]);
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
/* waiting for sending finish */
;
}
}
}
int uart_send(struct simple_buf *buf)
{
atomic_set(&uart_flag, UART_STATUS_SENDING);
uint8_t *send_data;
uint16_t send_len;
send_len = buf->len;
send_data = simple_buf_pull(buf, buf->len);
uart2_send_data(send_data, send_len);
atomic_set(&uart_flag, UART_STATUS_IDLE);
PRINT("uart2 send %d bytes [", send_len);
for(int i = 0; i < send_len; i++){
if(i) PRINT(" ");
PRINT("%#x", send_data[i]);
}
PRINT("]\n");
return 0;
}
/*********************************************************************
* @fn uart_processevent
*
* @brief process handle
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed
*/
tmosEvents uart_processevent(tmosTaskID task_id, tmosEvents events)
{
if(events & SYS_EVENT_MSG)
{
uint8_t *msgPtr;
msgPtr = tmos_msg_receive(task_id);
if(msgPtr)
{
/* De-allocate */
tmos_msg_deallocate(msgPtr);
}
return (events ^ SYS_EVENT_MSG);
}
if(events & UART_RECEIVE_POLL_EVT) {
if(atomic_get(&uart_flag) == UART_STATUS_RCV_END) {
PRINT("uart2 recevied %d bytes [", uart_buf->len);
for(int i = 0; i < uart_buf->len; i++) {
if(i) PRINT(" ");
PRINT("%#x", uart_buf->data[i]);
}
PRINT("]\n");
struct uart_process_msg *uart_msg;
uart_msg = (struct uart_process_msg *) \
tmos_msg_allocate(sizeof(struct uart_process_msg));
if(uart_msg) {
uart_msg->hdr.event = UART_PROCESS_EVT;
uart_msg->hdr.status = true;
uart_msg->data = (uint8_t *)uart_buf;
tmos_msg_send(test_taskid, (uint8_t *)uart_msg );
}
}
return (events ^ UART_RECEIVE_POLL_EVT);
}
return 0;
}
void uart_task_init(void)
{
uart_taskid = TMOS_ProcessEventRegister(uart_processevent);
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure = {0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* USART2 TX-->A.2 RX-->A.3 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
tmos_start_reload_task(uart_taskid, UART_RECEIVE_POLL_EVT,
MS1_TO_SYSTEM_TIME(100));
atomic_set(&uart_flag, UART_STATUS_IDLE);
uart_start_receiving();
}
/*********************************************************************
* @fn USART2_IRQHandler
*
* @brief This function handles USART2 global interrupt request.
*
* @return none
*/
__attribute__((interrupt("WCH-Interrupt-fast")))
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
simple_buf_add_u8(uart_buf, USART_ReceiveData(USART2));
}
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
{
atomic_set(&uart_flag, UART_STATUS_RCV_END);
/* clear IDLE flag */
(void)USART_ReceiveData(USART2);
}
}