Add bluetooth module and fix delay function in debug.c in ch32v208rbt6

1. Add command "test_ble" in shell to startup the ble module.
    The ble module could be found as "wch_ble_uart".
    But there is a bug: the command could be used only once before reset the board.
2. Fix a bug in Delay_Us function and Delay_Ms function in debug.c.
This commit is contained in:
huoyujia081 2024-06-03 14:26:25 +08:00
parent 75c13d656b
commit d75e3ad7f9
46 changed files with 27061 additions and 23 deletions

View File

@ -52,6 +52,11 @@ void Delay_Init(void)
*/
void Delay_Us(uint32_t n)
{
// 保存SysTick所有相关状态
u32 systick_ctlr = SysTick->CTLR;
u64 systick_cmp = SysTick->CMP;
u32 systick_sr = SysTick->SR;
uint32_t i;
SysTick->SR &= ~(1 << 0);
@ -63,6 +68,11 @@ void Delay_Us(uint32_t n)
while((SysTick->SR & (1 << 0)) != (1 << 0));
SysTick->CTLR &= ~(1 << 0);
// 恢复SysTick所有状态
SysTick->CTLR = systick_ctlr; // 恢复控制寄存器状态,包括中断使能、计数器使能等
SysTick->CMP = systick_cmp; // 恢复比较值
SysTick->SR = systick_sr; // 恢复状态寄存器状态,注意清中断位的操作应根据实际情况调整
}
/*********************************************************************
@ -78,12 +88,10 @@ void Delay_Ms(uint32_t n)
{
uint32_t i;
// 保存原始状态
if (originalSysTickState.SR == 0) {
originalSysTickState.SR = SysTick->SR;
originalSysTickState.CMP = SysTick->CMP;
originalSysTickState.CTLR = SysTick->CTLR;
}
// 保存SysTick所有相关状态
u32 systick_ctlr = SysTick->CTLR;
u64 systick_cmp = SysTick->CMP;
u32 systick_sr = SysTick->SR;
SysTick->SR &= ~(1 << 0);
i = (uint32_t)n * p_ms;
@ -94,10 +102,11 @@ void Delay_Ms(uint32_t n)
while((SysTick->SR & (1 << 0)) != (1 << 0));
SysTick->CTLR &= ~(1 << 0);
// 恢复原始状态
SysTick->SR = originalSysTickState.SR;
SysTick->CMP = originalSysTickState.CMP;
SysTick->CTLR = originalSysTickState.CTLR;
// 恢复SysTick所有状态
SysTick->CTLR = systick_ctlr; // 恢复控制寄存器状态,包括中断使能、计数器使能等
SysTick->CMP = systick_cmp; // 恢复比较值
SysTick->SR = systick_sr; // 恢复状态寄存器状态,注意清中断位的操作应根据实际情况调整
}
/*********************************************************************

View File

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

View File

@ -15,12 +15,13 @@
#include "ch32v20x_tim.h"
#include "eth_driver.h"
#include <xs_isr.h>
#include "wchble.h"
void NMI_Handler(void) __attribute__((interrupt()));
void HardFault_Handler(void) __attribute__((interrupt()));
void ETH_IRQHandler(void) __attribute__((interrupt()));
void TIM2_IRQHandler(void) __attribute__((interrupt()));
void BB_IRQHandler(void) __attribute__((interrupt()));
/*********************************************************************
* @fn NMI_Handler
*
@ -67,6 +68,7 @@ void HardFault_Handler(void)
*
* @return none
*/
#ifdef BSP_USING_ETH
void ETH_IRQHandler(void)
{
WCHNET_ETHIsr();
@ -86,5 +88,18 @@ void TIM2_IRQHandler(void)
WCHNET_TimeIsr(WCHNETTIMERPERIOD);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
#endif
/*********************************************************************
* @fn BB_IRQHandler
*
* @brief BB Interrupt for BLE.
*
* @return None
*/
#ifdef BSP_USING_BLE
void BB_IRQHandler(void)
{
BB_IRQLibHandler();
}
#endif

View File

@ -23,14 +23,14 @@
//#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_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_120MHz_HSI 120000000
//#define SYSCLK_FREQ_144MHz_HSI 144000000
/* Clock Definitions */

View File

@ -0,0 +1,127 @@
.global Ecall_M_Mode_Handler
.global Ecall_U_Mode_Handler
.global LLE_IRQHandler
.extern g_LLE_IRQLibHandlerLocation
.section .highcode,"ax",@progbits
.align 2
.func
Ecall_M_Mode_Handler:
Ecall_U_Mode_Handler:
addi a1, x0, 0x20
csrs 0x804, a1
lw a1, 0 * 4( sp )
csrw mepc, a1
lw x1, 1 * 4( sp )
lw x4, 2 * 4( sp )
lw x5, 3 * 4( sp )
lw x6, 4 * 4( sp )
lw x7, 5 * 4( sp )
lw x8, 6 * 4( sp )
lw x9, 7 * 4( sp )
lw x10, 8 * 4( sp )
lw x11, 9 * 4( sp )
lw x12, 10 * 4( sp )
lw x13, 11 * 4( sp )
lw x14, 12 * 4( sp )
lw x15, 13 * 4( sp )
lw x16, 14 * 4( sp )
lw x17, 15 * 4( sp )
lw x18, 16 * 4( sp )
lw x19, 17 * 4( sp )
lw x20, 18 * 4( sp )
lw x21, 19 * 4( sp )
lw x22, 20 * 4( sp )
lw x23, 21 * 4( sp )
lw x24, 22 * 4( sp )
lw x25, 23 * 4( sp )
lw x26, 24 * 4( sp )
lw x27, 25 * 4( sp )
lw x28, 26 * 4( sp )
lw x29, 27 * 4( sp )
lw x30, 28 * 4( sp )
lw x31, 29 * 4( sp )
addi sp, sp, 32*4
mret
.endfunc
.section .highcode.LLE_IRQHandler,"ax",@progbits
.align 2
.func
LLE_IRQHandler:
addi sp, sp, -32*4
sw x1, 1 * 4( sp )
sw x4, 2 * 4( sp )
sw x5, 3 * 4( sp )
sw x6, 4 * 4( sp )
sw x7, 5 * 4( sp )
sw x8, 6 * 4( sp )
sw x9, 7 * 4( sp )
sw x10, 8 * 4( sp )
sw x11, 9 * 4( sp )
sw x12, 10 * 4( sp )
sw x13, 11 * 4( sp )
sw x14, 12 * 4( sp )
sw x15, 13 * 4( sp )
sw x16, 14 * 4( sp )
sw x17, 15 * 4( sp )
sw x18, 16 * 4( sp )
sw x19, 17 * 4( sp )
sw x20, 18 * 4( sp )
sw x21, 19 * 4( sp )
sw x22, 20 * 4( sp )
sw x23, 21 * 4( sp )
sw x24, 22 * 4( sp )
sw x25, 23 * 4( sp )
sw x26, 24 * 4( sp )
sw x27, 25 * 4( sp )
sw x28, 26 * 4( sp )
sw x29, 27 * 4( sp )
sw x30, 28 * 4( sp )
sw x31, 29 * 4( sp )
la a1, g_LLE_IRQLibHandlerLocation
lw a0, 0(a1)
jalr x1, 0(a0)
lw x1, 1 * 4( sp )
lw x4, 2 * 4( sp )
lw x5, 3 * 4( sp )
lw x6, 4 * 4( sp )
lw x7, 5 * 4( sp )
lw x8, 6 * 4( sp )
lw x9, 7 * 4( sp )
lw x10, 8 * 4( sp )
lw x11, 9 * 4( sp )
lw x12, 10 * 4( sp )
lw x13, 11 * 4( sp )
lw x14, 12 * 4( sp )
lw x15, 13 * 4( sp )
lw x16, 14 * 4( sp )
lw x17, 15 * 4( sp )
lw x18, 16 * 4( sp )
lw x19, 17 * 4( sp )
lw x20, 18 * 4( sp )
lw x21, 19 * 4( sp )
lw x22, 20 * 4( sp )
lw x23, 21 * 4( sp )
lw x24, 22 * 4( sp )
lw x25, 23 * 4( sp )
lw x26, 24 * 4( sp )
lw x27, 25 * 4( sp )
lw x28, 26 * 4( sp )
lw x29, 27 * 4( sp )
lw x30, 28 * 4( sp )
lw x31, 29 * 4( sp )
addi sp, sp, 32*4
mret
.endfunc

View File

@ -38,6 +38,8 @@
#include <xs_base.h>
#include "connect_ether.h"
#include "adc.h"
#include "third_party_driver/ble/inc/wchble.h"
#include "third_party_driver/ble/inc/HAL.h"
// core clock.
extern uint32_t SystemCoreClock;
@ -67,14 +69,24 @@ void InitBoardHardware()
_SysTick_Config(SystemCoreClock / TICK_PER_SECOND);
/* 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);
#endif
#ifdef BSP_USING_ETH
InitHwEth();
#endif
#ifdef BSP_USING_ADC
ADC_Function_Init();
#endif
#ifdef BSP_USING_BLE
WCHBLE_Init();
HAL_Init();
#endif
KPrintf("consle init completed.\n");
KPrintf("board initialization......\n");
// KPrintf("memory address range: [0x%08x - 0x%08x], size: %d\n", (x_ubase) MEMORY_START_ADDRESS, (x_ubase) MEMORY_END_ADDRESS, gd32vf103_SRAM_SIZE);

View File

@ -36,12 +36,12 @@ Modification:
#define ch32v20x_PIN_NUMBERS 48
/* board configuration */
#define SRAM_SIZE 48
#define SRAM_SIZE 64
#define EUSR_STACK_SIZE 2048
// #define SRAM_END (0x20000000 + SRAM_SIZE * 0x400)
// #define SRAM_END (0x20008000)
#define SRAM_END (0x2000C000)
#define SRAM_END (0x20010000)
extern int _ebss;
extern int __stack_size;
#define MEMORY_START_ADDRESS ((void *)&_ebss)

View File

@ -16,6 +16,7 @@ export CROSS_COMPILE ?=/opt/riscv64-toolchain/bin/riscv64-unknown-elf-
export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO
export LINK_WCH_NET := $(KERNEL_ROOT)/board/ch32v208rbt6/third_party_driver/ethernet/libwchnet.a
export LINK_WCH_BLE := $(KERNEL_ROOT)/board/ch32v208rbt6/third_party_driver/ble/lib/libwchble.a
export ARCH = risc-v
export MCU = CH32V208

View File

@ -17,7 +17,7 @@ MEMORY
/*
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
*/
*/
/* CH32V20x_D8 - CH32V203RB
CH32V20x_D8W - CH32V208x
@ -26,8 +26,8 @@ MEMORY
FLASH-144K + RAM-48K
FLASH-160K + RAM-32K
*/
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 144K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
}
@ -48,14 +48,26 @@ SECTIONS
*(.vector);
. = ALIGN(64);
} >FLASH AT>FLASH
.highcode :
{
. = ALIGN(4);
*(.highcode);
*(.highcode.*);
. = ALIGN(4);
} >FLASH AT>FLASH
.text :
{
. = ALIGN(4);
EXCLUDE_FILE (*wchble.a) *(.text .text*)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata*)
*(.sdata2.*)
*(.glue_7)
*(.glue_7t)
*(.gnu.linkonce.t.*)
. = ALIGN(4);

View File

@ -1,4 +1,3 @@
menuconfig BSP_USING_UART
bool "Using UART device"
default y
@ -14,4 +13,8 @@ menuconfig BSP_USING_ETH
menuconfig BSP_USING_ADC
bool "Using ADC"
default y
menuconfig BSP_USING_BLE
bool "Using BLE"
default y

View File

@ -10,4 +10,7 @@ endif
ifeq ($(CONFIG_BSP_USING_ADC),y)
SRC_DIR += adc
endif
ifeq ($(CONFIG_BSP_USING_BLE),y)
SRC_DIR += ble
endif
include $(KERNEL_ROOT)/compiler.mk

View File

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

View File

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

View File

@ -0,0 +1,588 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : devinfoservice.c
* Author : WCH
* Version : V1.0
* Date : 2018/12/10
* Description : Device information service
*********************************************************************************
* 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 "../inc/config.h"
#include "devinfoservice.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
// Device information service
const uint8_t devInfoServUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(DEVINFO_SERV_UUID), HI_UINT16(DEVINFO_SERV_UUID)};
// System ID
const uint8_t devInfoSystemIdUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SYSTEM_ID_UUID), HI_UINT16(SYSTEM_ID_UUID)};
// Model Number String
const uint8_t devInfoModelNumberUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(MODEL_NUMBER_UUID), HI_UINT16(MODEL_NUMBER_UUID)};
// Serial Number String
const uint8_t devInfoSerialNumberUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SERIAL_NUMBER_UUID), HI_UINT16(SERIAL_NUMBER_UUID)};
// Firmware Revision String
const uint8_t devInfoFirmwareRevUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(FIRMWARE_REV_UUID), HI_UINT16(FIRMWARE_REV_UUID)};
// Hardware Revision String
const uint8_t devInfoHardwareRevUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(HARDWARE_REV_UUID), HI_UINT16(HARDWARE_REV_UUID)};
// Software Revision String
const uint8_t devInfoSoftwareRevUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SOFTWARE_REV_UUID), HI_UINT16(SOFTWARE_REV_UUID)};
// Manufacturer Name String
const uint8_t devInfoMfrNameUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(MANUFACTURER_NAME_UUID), HI_UINT16(MANUFACTURER_NAME_UUID)};
// IEEE 11073-20601 Regulatory Certification Data List
const uint8_t devInfo11073CertUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(IEEE_11073_CERT_DATA_UUID), HI_UINT16(IEEE_11073_CERT_DATA_UUID)};
// PnP ID
const uint8_t devInfoPnpIdUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(PNP_ID_UUID), HI_UINT16(PNP_ID_UUID)};
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
/*********************************************************************
* Profile Attributes - variables
*/
// Device Information Service attribute
static const gattAttrType_t devInfoService = {ATT_BT_UUID_SIZE, devInfoServUUID};
// System ID characteristic
static uint8_t devInfoSystemIdProps = GATT_PROP_READ;
static uint8_t devInfoSystemId[DEVINFO_SYSTEM_ID_LEN] = {0, 0, 0, 0, 0, 0, 0, 0};
// Model Number String characteristic
static uint8_t devInfoModelNumberProps = GATT_PROP_READ;
static const uint8_t devInfoModelNumber[] = "Model Number";
// Serial Number String characteristic
static uint8_t devInfoSerialNumberProps = GATT_PROP_READ;
static const uint8_t devInfoSerialNumber[] = "Serial Number";
// Firmware Revision String characteristic
static uint8_t devInfoFirmwareRevProps = GATT_PROP_READ;
static const uint8_t devInfoFirmwareRev[] = "Firmware Revision";
// Hardware Revision String characteristic
static uint8_t devInfoHardwareRevProps = GATT_PROP_READ;
static const uint8_t devInfoHardwareRev[] = "Hardware Revision";
// Software Revision String characteristic
static uint8_t devInfoSoftwareRevProps = GATT_PROP_READ;
static const uint8_t devInfoSoftwareRev[] = "Software Revision";
// Manufacturer Name String characteristic
static uint8_t devInfoMfrNameProps = GATT_PROP_READ;
static const uint8_t devInfoMfrName[] = "Manufacturer Name";
// IEEE 11073-20601 Regulatory Certification Data List characteristic
static uint8_t devInfo11073CertProps = GATT_PROP_READ;
static const uint8_t devInfo11073Cert[] = {
DEVINFO_11073_BODY_EXP, // authoritative body type
0x00, // authoritative body structure type
// authoritative body data follows below:
'e', 'x', 'p', 'e', 'r', 'i', 'm', 'e', 'n', 't', 'a', 'l'};
// System ID characteristic
static uint8_t devInfoPnpIdProps = GATT_PROP_READ;
static uint8_t devInfoPnpId[DEVINFO_PNP_ID_LEN] = {
1, // Vendor ID source (1=Bluetooth SIG)
LO_UINT16(0x07D7), HI_UINT16(0x07D7), // Vendor ID (WCH)
LO_UINT16(0x0000), HI_UINT16(0x0000), // Product ID (vendor-specific)
LO_UINT16(0x0110), HI_UINT16(0x0110) // Product version (JJ.M.N)
};
/*********************************************************************
* Profile Attributes - Table
*/
static gattAttribute_t devInfoAttrTbl[] = {
// Device Information Service
{
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8_t *)&devInfoService /* pValue */
},
// System ID Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoSystemIdProps},
// System ID Value
{
{ATT_BT_UUID_SIZE, devInfoSystemIdUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoSystemId},
// Model Number String Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoModelNumberProps},
// Model Number Value
{
{ATT_BT_UUID_SIZE, devInfoModelNumberUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoModelNumber},
// Serial Number String Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoSerialNumberProps},
// Serial Number Value
{
{ATT_BT_UUID_SIZE, devInfoSerialNumberUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoSerialNumber},
// Firmware Revision String Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoFirmwareRevProps},
// Firmware Revision Value
{
{ATT_BT_UUID_SIZE, devInfoFirmwareRevUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoFirmwareRev},
// Hardware Revision String Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoHardwareRevProps},
// Hardware Revision Value
{
{ATT_BT_UUID_SIZE, devInfoHardwareRevUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoHardwareRev},
// Software Revision String Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoSoftwareRevProps},
// Software Revision Value
{
{ATT_BT_UUID_SIZE, devInfoSoftwareRevUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoSoftwareRev},
// Manufacturer Name String Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoMfrNameProps},
// Manufacturer Name Value
{
{ATT_BT_UUID_SIZE, devInfoMfrNameUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoMfrName},
// IEEE 11073-20601 Regulatory Certification Data List Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfo11073CertProps},
// IEEE 11073-20601 Regulatory Certification Data List Value
{
{ATT_BT_UUID_SIZE, devInfo11073CertUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfo11073Cert},
// PnP ID Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&devInfoPnpIdProps},
// PnP ID Value
{
{ATT_BT_UUID_SIZE, devInfoPnpIdUUID},
GATT_PERMIT_READ,
0,
(uint8_t *)devInfoPnpId}};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
/*********************************************************************
* PROFILE CALLBACKS
*/
// Device Info Service Callbacks
gattServiceCBs_t devInfoCBs = {
devInfo_ReadAttrCB, // Read callback function pointer
NULL, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************************
* NETWORK LAYER CALLBACKS
*/
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn DevInfo_AddService
*
* @brief Initializes the Device Information service by registering
* GATT attributes with the GATT server.
*
* @return Success or Failure
*/
bStatus_t DevInfo_AddService(void)
{
// Register GATT attribute list and CBs with GATT Server App
return GATTServApp_RegisterService(devInfoAttrTbl,
GATT_NUM_ATTRS(devInfoAttrTbl),
GATT_MAX_ENCRYPT_KEY_SIZE,
&devInfoCBs);
}
/*********************************************************************
* @fn DevInfo_SetParameter
*
* @brief Set a Device Information parameter.
*
* @param param - Profile parameter ID
* @param len - length of data to write
* @param value - pointer to data to write. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return bStatus_t
*/
bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value)
{
bStatus_t ret = SUCCESS;
switch(param)
{
case DEVINFO_SYSTEM_ID:
tmos_memcpy(devInfoSystemId, value, len);
break;
default:
ret = INVALIDPARAMETER;
break;
}
return (ret);
}
/*********************************************************************
* @fn DevInfo_GetParameter
*
* @brief Get a Device Information parameter.
*
* @param param - Profile parameter ID
* @param value - pointer to data to get. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return bStatus_t
*/
bStatus_t DevInfo_GetParameter(uint8_t param, void *value)
{
bStatus_t ret = SUCCESS;
switch(param)
{
case DEVINFO_SYSTEM_ID:
tmos_memcpy(value, devInfoSystemId, sizeof(devInfoSystemId));
break;
case DEVINFO_MODEL_NUMBER:
tmos_memcpy(value, devInfoModelNumber, sizeof(devInfoModelNumber));
break;
case DEVINFO_SERIAL_NUMBER:
tmos_memcpy(value, devInfoSerialNumber, sizeof(devInfoSerialNumber));
break;
case DEVINFO_FIRMWARE_REV:
tmos_memcpy(value, devInfoFirmwareRev, sizeof(devInfoFirmwareRev));
break;
case DEVINFO_HARDWARE_REV:
tmos_memcpy(value, devInfoHardwareRev, sizeof(devInfoHardwareRev));
break;
case DEVINFO_SOFTWARE_REV:
tmos_memcpy(value, devInfoSoftwareRev, sizeof(devInfoSoftwareRev));
break;
case DEVINFO_MANUFACTURER_NAME:
tmos_memcpy(value, devInfoMfrName, sizeof(devInfoMfrName));
break;
case DEVINFO_11073_CERT_DATA:
tmos_memcpy(value, devInfo11073Cert, sizeof(devInfo11073Cert));
break;
case DEVINFO_PNP_ID:
tmos_memcpy(value, devInfoPnpId, sizeof(devInfoPnpId));
break;
default:
ret = INVALIDPARAMETER;
break;
}
return (ret);
}
/*********************************************************************
* @fn devInfo_ReadAttrCB
*
* @brief Read an attribute.
*
* @param connHandle - connection message was received on
* @param pAttr - pointer to attribute
* @param pValue - pointer to data to be read
* @param pLen - length of data to be read
* @param offset - offset of the first octet to be read
* @param maxLen - maximum length of data to be read
*
* @return Success or Failure
*/
static bStatus_t devInfo_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
{
bStatus_t status = SUCCESS;
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch(uuid)
{
case SYSTEM_ID_UUID:
// verify offset
if(offset >= sizeof(devInfoSystemId))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length
*pLen = MIN(maxLen, (sizeof(devInfoSystemId) - offset));
// copy data
tmos_memcpy(pValue, &devInfoSystemId[offset], *pLen);
}
break;
case MODEL_NUMBER_UUID:
// verify offset
if(offset >= (sizeof(devInfoModelNumber) - 1))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length (exclude null terminating character)
*pLen = MIN(maxLen, ((sizeof(devInfoModelNumber) - 1) - offset));
// copy data
tmos_memcpy(pValue, &devInfoModelNumber[offset], *pLen);
}
break;
case SERIAL_NUMBER_UUID:
// verify offset
if(offset >= (sizeof(devInfoSerialNumber) - 1))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length (exclude null terminating character)
*pLen = MIN(maxLen, ((sizeof(devInfoSerialNumber) - 1) - offset));
// copy data
tmos_memcpy(pValue, &devInfoSerialNumber[offset], *pLen);
}
break;
case FIRMWARE_REV_UUID:
// verify offset
if(offset >= (sizeof(devInfoFirmwareRev) - 1))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length (exclude null terminating character)
*pLen = MIN(maxLen, ((sizeof(devInfoFirmwareRev) - 1) - offset));
// copy data
tmos_memcpy(pValue, &devInfoFirmwareRev[offset], *pLen);
}
break;
case HARDWARE_REV_UUID:
// verify offset
if(offset >= (sizeof(devInfoHardwareRev) - 1))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length (exclude null terminating character)
*pLen = MIN(maxLen, ((sizeof(devInfoHardwareRev) - 1) - offset));
// copy data
tmos_memcpy(pValue, &devInfoHardwareRev[offset], *pLen);
}
break;
case SOFTWARE_REV_UUID:
// verify offset
if(offset >= (sizeof(devInfoSoftwareRev) - 1))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length (exclude null terminating character)
*pLen = MIN(maxLen, ((sizeof(devInfoSoftwareRev) - 1) - offset));
// copy data
tmos_memcpy(pValue, &devInfoSoftwareRev[offset], *pLen);
}
break;
case MANUFACTURER_NAME_UUID:
// verify offset
if(offset >= (sizeof(devInfoMfrName) - 1))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length (exclude null terminating character)
*pLen = MIN(maxLen, ((sizeof(devInfoMfrName) - 1) - offset));
// copy data
tmos_memcpy(pValue, &devInfoMfrName[offset], *pLen);
}
break;
case IEEE_11073_CERT_DATA_UUID:
// verify offset
if(offset >= sizeof(devInfo11073Cert))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length
*pLen = MIN(maxLen, (sizeof(devInfo11073Cert) - offset));
// copy data
tmos_memcpy(pValue, &devInfo11073Cert[offset], *pLen);
}
break;
case PNP_ID_UUID:
// verify offset
if(offset >= sizeof(devInfoPnpId))
{
status = ATT_ERR_INVALID_OFFSET;
}
else
{
// determine read length
*pLen = MIN(maxLen, (sizeof(devInfoPnpId) - offset));
// copy data
tmos_memcpy(pValue, &devInfoPnpId[offset], *pLen);
}
break;
default:
*pLen = 0;
status = ATT_ERR_ATTR_NOT_FOUND;
break;
}
return (status);
}
/*********************************************************************
*********************************************************************/

View File

@ -0,0 +1,109 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : devinfoservice.h
* Author : WCH
* Version : V1.0
* Date : 2018/12/11
* 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 DEVINFOSERVICE_H
#define DEVINFOSERVICE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* INCLUDES
*/
/*********************************************************************
* CONSTANTS
*/
// Device Information Service Parameters
#define DEVINFO_SYSTEM_ID 0
#define DEVINFO_MODEL_NUMBER 1
#define DEVINFO_SERIAL_NUMBER 2
#define DEVINFO_FIRMWARE_REV 3
#define DEVINFO_HARDWARE_REV 4
#define DEVINFO_SOFTWARE_REV 5
#define DEVINFO_MANUFACTURER_NAME 6
#define DEVINFO_11073_CERT_DATA 7
#define DEVINFO_PNP_ID 8
// IEEE 11073 authoritative body values
#define DEVINFO_11073_BODY_EMPTY 0
#define DEVINFO_11073_BODY_IEEE 1
#define DEVINFO_11073_BODY_CONTINUA 2
#define DEVINFO_11073_BODY_EXP 254
// System ID length
#define DEVINFO_SYSTEM_ID_LEN 8
// PnP ID length
#define DEVINFO_PNP_ID_LEN 7
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* MACROS
*/
/*********************************************************************
* Profile Callbacks
*/
/*********************************************************************
* API FUNCTIONS
*/
/*
* DevInfo_AddService- Initializes the Device Information service by registering
* GATT attributes with the GATT server.
*
*/
extern bStatus_t DevInfo_AddService(void);
/*********************************************************************
* @fn DevInfo_SetParameter
*
* @brief Set a Device Information parameter.
*
* @param param - Profile parameter ID
* @param len - length of data to right
* @param value - pointer to data to write. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return bStatus_t
*/
bStatus_t DevInfo_SetParameter(uint8_t param, uint8_t len, void *value);
/*
* DevInfo_GetParameter - Get a Device Information parameter.
*
* param - Profile parameter ID
* value - pointer to data to write. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*/
extern bStatus_t DevInfo_GetParameter(uint8_t param, void *value);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* DEVINFOSERVICE_H */

View File

@ -0,0 +1,703 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : gattprofile.C
* Author : WCH
* Version : V1.0
* Date : 2018/12/10
* Description : Customized services containing five different attributes,
* including readable, written, notified, readable, readable,
* safe readable available
*********************************************************************************
* 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 "../inc/config.h"
#include "gattprofile.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
// Position of simpleProfilechar4 value in attribute array
#define SIMPLEPROFILE_CHAR4_VALUE_POS 11
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
// Simple GATT Profile Service UUID: 0xFFF0
const uint8_t simpleProfileServUUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
// Characteristic 1 UUID: 0xFFF1
const uint8_t simpleProfilechar1UUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)};
// Characteristic 2 UUID: 0xFFF2
const uint8_t simpleProfilechar2UUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID)};
// Characteristic 3 UUID: 0xFFF3
const uint8_t simpleProfilechar3UUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SIMPLEPROFILE_CHAR3_UUID), HI_UINT16(SIMPLEPROFILE_CHAR3_UUID)};
// Characteristic 4 UUID: 0xFFF4
const uint8_t simpleProfilechar4UUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID)};
// Characteristic 5 UUID: 0xFFF5
const uint8_t simpleProfilechar5UUID[ATT_BT_UUID_SIZE] = {
LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID)};
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;
/*********************************************************************
* Profile Attributes - variables
*/
// Simple Profile Service attribute
static const gattAttrType_t simpleProfileService = {ATT_BT_UUID_SIZE, simpleProfileServUUID};
// Simple Profile Characteristic 1 Properties
static uint8_t simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE;
// Characteristic 1 Value
static uint8_t simpleProfileChar1[SIMPLEPROFILE_CHAR1_LEN] = {0};
// Simple Profile Characteristic 1 User Description
static uint8_t simpleProfileChar1UserDesp[] = "Characteristic 1\0";
// Simple Profile Characteristic 2 Properties
static uint8_t simpleProfileChar2Props = GATT_PROP_READ;
// Characteristic 2 Value
static uint8_t simpleProfileChar2[SIMPLEPROFILE_CHAR2_LEN] = {0};
// Simple Profile Characteristic 2 User Description
static uint8_t simpleProfileChar2UserDesp[] = "Characteristic 2\0";
// Simple Profile Characteristic 3 Properties
static uint8_t simpleProfileChar3Props = GATT_PROP_WRITE;
// Characteristic 3 Value
static uint8_t simpleProfileChar3[SIMPLEPROFILE_CHAR3_LEN] = {0};
// Simple Profile Characteristic 3 User Description
static uint8_t simpleProfileChar3UserDesp[] = "Characteristic 3\0";
// Simple Profile Characteristic 4 Properties
static uint8_t simpleProfileChar4Props = GATT_PROP_NOTIFY;
// Characteristic 4 Value
static uint8_t simpleProfileChar4[SIMPLEPROFILE_CHAR4_LEN] = {0};
// Simple Profile Characteristic 4 Configuration Each client has its own
// instantiation of the Client Characteristic Configuration. Reads of the
// Client Characteristic Configuration only shows the configuration for
// that client and writes only affect the configuration of that client.
static gattCharCfg_t simpleProfileChar4Config[4];
// Simple Profile Characteristic 4 User Description
static uint8_t simpleProfileChar4UserDesp[] = "Characteristic 4\0";
// Simple Profile Characteristic 5 Properties
static uint8_t simpleProfileChar5Props = GATT_PROP_READ;
// Characteristic 5 Value
static uint8_t simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = {0};
// Simple Profile Characteristic 5 User Description
static uint8_t simpleProfileChar5UserDesp[] = "Characteristic 5\0";
/*********************************************************************
* Profile Attributes - Table
*/
static gattAttribute_t simpleProfileAttrTbl[] = {
// Simple Profile Service
{
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8_t *)&simpleProfileService /* pValue */
},
// Characteristic 1 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&simpleProfileChar1Props},
// Characteristic Value 1
{
{ATT_BT_UUID_SIZE, simpleProfilechar1UUID},
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
simpleProfileChar1},
// Characteristic 1 User Description
{
{ATT_BT_UUID_SIZE, charUserDescUUID},
GATT_PERMIT_READ,
0,
simpleProfileChar1UserDesp},
// Characteristic 2 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&simpleProfileChar2Props},
// Characteristic Value 2
{
{ATT_BT_UUID_SIZE, simpleProfilechar2UUID},
GATT_PERMIT_READ,
0,
simpleProfileChar2},
// Characteristic 2 User Description
{
{ATT_BT_UUID_SIZE, charUserDescUUID},
GATT_PERMIT_READ,
0,
simpleProfileChar2UserDesp},
// Characteristic 3 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&simpleProfileChar3Props},
// Characteristic Value 3
{
{ATT_BT_UUID_SIZE, simpleProfilechar3UUID},
GATT_PERMIT_WRITE,
0,
simpleProfileChar3},
// Characteristic 3 User Description
{
{ATT_BT_UUID_SIZE, charUserDescUUID},
GATT_PERMIT_READ,
0,
simpleProfileChar3UserDesp},
// Characteristic 4 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&simpleProfileChar4Props},
// Characteristic Value 4
{
{ATT_BT_UUID_SIZE, simpleProfilechar4UUID},
0,
0,
simpleProfileChar4},
// Characteristic 4 configuration
{
{ATT_BT_UUID_SIZE, clientCharCfgUUID},
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8_t *)simpleProfileChar4Config},
// Characteristic 4 User Description
{
{ATT_BT_UUID_SIZE, charUserDescUUID},
GATT_PERMIT_READ,
0,
simpleProfileChar4UserDesp},
// Characteristic 5 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&simpleProfileChar5Props},
// Characteristic Value 5
{
{ATT_BT_UUID_SIZE, simpleProfilechar5UUID},
GATT_PERMIT_AUTHEN_READ,
0,
simpleProfileChar5},
// Characteristic 5 User Description
{
{ATT_BT_UUID_SIZE, charUserDescUUID},
GATT_PERMIT_READ,
0,
simpleProfileChar5UserDesp},
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
static void simpleProfile_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
/*********************************************************************
* PROFILE CALLBACKS
*/
// Simple Profile Service Callbacks
gattServiceCBs_t simpleProfileCBs = {
simpleProfile_ReadAttrCB, // Read callback function pointer
simpleProfile_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn SimpleProfile_AddService
*
* @brief Initializes the Simple Profile service by registering
* GATT attributes with the GATT server.
*
* @param services - services to add. This is a bit map and can
* contain more than one service.
*
* @return Success or Failure
*/
bStatus_t SimpleProfile_AddService(uint32_t services)
{
uint8_t status = SUCCESS;
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, simpleProfileChar4Config);
// Register with Link DB to receive link status change callback
linkDB_Register(simpleProfile_HandleConnStatusCB);
if(services & SIMPLEPROFILE_SERVICE)
{
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService(simpleProfileAttrTbl,
GATT_NUM_ATTRS(simpleProfileAttrTbl),
GATT_MAX_ENCRYPT_KEY_SIZE,
&simpleProfileCBs);
}
return (status);
}
/*********************************************************************
* @fn SimpleProfile_RegisterAppCBs
*
* @brief Registers the application callback function. Only call
* this function once.
*
* @param callbacks - pointer to application callbacks.
*
* @return SUCCESS or bleAlreadyInRequestedMode
*/
bStatus_t SimpleProfile_RegisterAppCBs(simpleProfileCBs_t *appCallbacks)
{
if(appCallbacks)
{
simpleProfile_AppCBs = appCallbacks;
return (SUCCESS);
}
else
{
return (bleAlreadyInRequestedMode);
}
}
/*********************************************************************
* @fn SimpleProfile_SetParameter
*
* @brief Set a Simple Profile parameter.
*
* @param param - Profile parameter ID
* @param len - length of data to right
* @param value - pointer to data to write. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return bStatus_t
*/
bStatus_t SimpleProfile_SetParameter(uint8_t param, uint8_t len, void *value)
{
bStatus_t ret = SUCCESS;
switch(param)
{
case SIMPLEPROFILE_CHAR1:
if(len == SIMPLEPROFILE_CHAR1_LEN)
{
tmos_memcpy(simpleProfileChar1, value, SIMPLEPROFILE_CHAR1_LEN);
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_CHAR2:
if(len == SIMPLEPROFILE_CHAR2_LEN)
{
tmos_memcpy(simpleProfileChar2, value, SIMPLEPROFILE_CHAR2_LEN);
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_CHAR3:
if(len == SIMPLEPROFILE_CHAR3_LEN)
{
tmos_memcpy(simpleProfileChar3, value, SIMPLEPROFILE_CHAR3_LEN);
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_CHAR4:
if(len == SIMPLEPROFILE_CHAR4_LEN)
{
tmos_memcpy(simpleProfileChar4, value, SIMPLEPROFILE_CHAR4_LEN);
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_CHAR5:
if(len == SIMPLEPROFILE_CHAR5_LEN)
{
tmos_memcpy(simpleProfileChar5, value, SIMPLEPROFILE_CHAR5_LEN);
}
else
{
ret = bleInvalidRange;
}
break;
default:
ret = INVALIDPARAMETER;
break;
}
return (ret);
}
/*********************************************************************
* @fn SimpleProfile_GetParameter
*
* @brief Get a Simple Profile parameter.
*
* @param param - Profile parameter ID
* @param value - pointer to data to put. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*
* @return bStatus_t
*/
bStatus_t SimpleProfile_GetParameter(uint8_t param, void *value)
{
bStatus_t ret = SUCCESS;
switch(param)
{
case SIMPLEPROFILE_CHAR1:
tmos_memcpy(value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN);
break;
case SIMPLEPROFILE_CHAR2:
tmos_memcpy(value, simpleProfileChar2, SIMPLEPROFILE_CHAR2_LEN);
break;
case SIMPLEPROFILE_CHAR3:
tmos_memcpy(value, simpleProfileChar3, SIMPLEPROFILE_CHAR3_LEN);
break;
case SIMPLEPROFILE_CHAR4:
tmos_memcpy(value, simpleProfileChar4, SIMPLEPROFILE_CHAR4_LEN);
break;
case SIMPLEPROFILE_CHAR5:
tmos_memcpy(value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN);
break;
default:
ret = INVALIDPARAMETER;
break;
}
return (ret);
}
/*********************************************************************
* @fn simpleProfile_Notify
*
* @brief Send a notification containing a heart rate
* measurement.
*
* @param connHandle - connection handle
* @param pNoti - pointer to notification structure
*
* @return Success or Failure
*/
bStatus_t simpleProfile_Notify(uint16_t connHandle, attHandleValueNoti_t *pNoti)
{
uint16_t value = GATTServApp_ReadCharCfg(connHandle, simpleProfileChar4Config);
// If notifications enabled
if(value & GATT_CLIENT_CFG_NOTIFY)
{
// Set the handle
pNoti->handle = simpleProfileAttrTbl[SIMPLEPROFILE_CHAR4_VALUE_POS].handle;
// Send the notification
return GATT_Notification(connHandle, pNoti, FALSE);
}
return bleIncorrectMode;
}
/*********************************************************************
* @fn simpleProfile_ReadAttrCB
*
* @brief Read an attribute.
*
* @param connHandle - connection message was received on
* @param pAttr - pointer to attribute
* @param pValue - pointer to data to be read
* @param pLen - length of data to be read
* @param offset - offset of the first octet to be read
* @param maxLen - maximum length of data to be read
*
* @return Success or Failure
*/
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
{
bStatus_t status = SUCCESS;
// Make sure it's not a blob operation (no attributes in the profile are long)
if(offset > 0)
{
return (ATT_ERR_ATTR_NOT_LONG);
}
if(pAttr->type.len == ATT_BT_UUID_SIZE)
{
// 16-bit UUID
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch(uuid)
{
// No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
// gattserverapp handles those reads
// characteristics 1 and 2 have read permissions
// characteritisc 3 does not have read permissions; therefore it is not
// included here
// characteristic 4 does not have read permissions, but because it
// can be sent as a notification, it is included here
case SIMPLEPROFILE_CHAR1_UUID:
*pLen = SIMPLEPROFILE_CHAR1_LEN;
tmos_memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN);
break;
case SIMPLEPROFILE_CHAR2_UUID:
*pLen = SIMPLEPROFILE_CHAR2_LEN;
tmos_memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR2_LEN);
break;
case SIMPLEPROFILE_CHAR4_UUID:
*pLen = SIMPLEPROFILE_CHAR4_LEN;
tmos_memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR4_LEN);
break;
case SIMPLEPROFILE_CHAR5_UUID:
*pLen = SIMPLEPROFILE_CHAR5_LEN;
tmos_memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN);
break;
default:
// Should never get here! (characteristics 3 and 4 do not have read permissions)
*pLen = 0;
status = ATT_ERR_ATTR_NOT_FOUND;
break;
}
}
else
{
// 128-bit UUID
*pLen = 0;
status = ATT_ERR_INVALID_HANDLE;
}
return (status);
}
/*********************************************************************
* @fn simpleProfile_WriteAttrCB
*
* @brief Validate attribute data prior to a write operation
*
* @param connHandle - connection message was received on
* @param pAttr - pointer to attribute
* @param pValue - pointer to data to be written
* @param len - length of data
* @param offset - offset of the first octet to be written
*
* @return Success or Failure
*/
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
{
bStatus_t status = SUCCESS;
uint8_t notifyApp = 0xFF;
// If attribute permissions require authorization to write, return error
if(gattPermitAuthorWrite(pAttr->permissions))
{
// Insufficient authorization
return (ATT_ERR_INSUFFICIENT_AUTHOR);
}
if(pAttr->type.len == ATT_BT_UUID_SIZE)
{
// 16-bit UUID
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch(uuid)
{
case SIMPLEPROFILE_CHAR1_UUID:
//Validate the value
// Make sure it's not a blob oper
if(offset == 0)
{
if(len > SIMPLEPROFILE_CHAR1_LEN)
{
status = ATT_ERR_INVALID_VALUE_SIZE;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
//Write the value
if(status == SUCCESS)
{
tmos_memcpy(pAttr->pValue, pValue, SIMPLEPROFILE_CHAR1_LEN);
notifyApp = SIMPLEPROFILE_CHAR1;
}
break;
case SIMPLEPROFILE_CHAR3_UUID:
//Validate the value
// Make sure it's not a blob oper
if(offset == 0)
{
if(len > SIMPLEPROFILE_CHAR3_LEN)
{
status = ATT_ERR_INVALID_VALUE_SIZE;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
//Write the value
if(status == SUCCESS)
{
tmos_memcpy(pAttr->pValue, pValue, SIMPLEPROFILE_CHAR3_LEN);
notifyApp = SIMPLEPROFILE_CHAR3;
}
break;
case GATT_CLIENT_CHAR_CFG_UUID:
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
offset, GATT_CLIENT_CFG_NOTIFY);
break;
default:
// Should never get here! (characteristics 2 and 4 do not have write permissions)
status = ATT_ERR_ATTR_NOT_FOUND;
break;
}
}
else
{
// 128-bit UUID
status = ATT_ERR_INVALID_HANDLE;
}
// If a charactersitic value changed then callback function to notify application of change
if((notifyApp != 0xFF) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange)
{
simpleProfile_AppCBs->pfnSimpleProfileChange(notifyApp);
}
return (status);
}
/*********************************************************************
* @fn simpleProfile_HandleConnStatusCB
*
* @brief Simple Profile link status change handler function.
*
* @param connHandle - connection handle
* @param changeType - type of change
*
* @return none
*/
static void simpleProfile_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
{
// Make sure this is not loopback connection
if(connHandle != LOOPBACK_CONNHANDLE)
{
// Reset Client Char Config if connection has dropped
if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
(!linkDB_Up(connHandle))))
{
GATTServApp_InitCharCfg(connHandle, simpleProfileChar4Config);
}
}
}
/*********************************************************************
*********************************************************************/

View File

@ -0,0 +1,135 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : gattprofile.h
* Author : WCH
* Version : V1.0
* Date : 2018/12/11
* 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 GATTPROFILE_H
#define GATTPROFILE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* INCLUDES
*/
/*********************************************************************
* CONSTANTS
*/
// Profile Parameters
#define SIMPLEPROFILE_CHAR1 0 // RW uint8_t - Profile Characteristic 1 value
#define SIMPLEPROFILE_CHAR2 1 // RW uint8_t - Profile Characteristic 2 value
#define SIMPLEPROFILE_CHAR3 2 // RW uint8_t - Profile Characteristic 3 value
#define SIMPLEPROFILE_CHAR4 3 // RW uint8_t - Profile Characteristic 4 value
#define SIMPLEPROFILE_CHAR5 4 // RW uint8_t - Profile Characteristic 4 value
// Simple Profile Service UUID
#define SIMPLEPROFILE_SERV_UUID 0xFFE0
// Key Pressed UUID
#define SIMPLEPROFILE_CHAR1_UUID 0xFFE1
#define SIMPLEPROFILE_CHAR2_UUID 0xFFE2
#define SIMPLEPROFILE_CHAR3_UUID 0xFFE3
#define SIMPLEPROFILE_CHAR4_UUID 0xFFE4
#define SIMPLEPROFILE_CHAR5_UUID 0xFFE5
// Simple Keys Profile Services bit fields
#define SIMPLEPROFILE_SERVICE 0x00000001
// Length of characteristic in bytes ( Default MTU is 23 )
#define SIMPLEPROFILE_CHAR1_LEN 1
#define SIMPLEPROFILE_CHAR2_LEN 1
#define SIMPLEPROFILE_CHAR3_LEN 1
#define SIMPLEPROFILE_CHAR4_LEN 1
#define SIMPLEPROFILE_CHAR5_LEN 5
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* MACROS
*/
/*********************************************************************
* Profile Callbacks
*/
// Callback when a characteristic value has changed
typedef void (*simpleProfileChange_t)(uint8_t paramID);
typedef struct
{
simpleProfileChange_t pfnSimpleProfileChange; // Called when characteristic value changes
} simpleProfileCBs_t;
/*********************************************************************
* API FUNCTIONS
*/
/*
* SimpleProfile_AddService- Initializes the Simple GATT Profile service by registering
* GATT attributes with the GATT server.
*
* @param services - services to add. This is a bit map and can
* contain more than one service.
*/
extern bStatus_t SimpleProfile_AddService(uint32_t services);
/*
* SimpleProfile_RegisterAppCBs - Registers the application callback function.
* Only call this function once.
*
* appCallbacks - pointer to application callbacks.
*/
extern bStatus_t SimpleProfile_RegisterAppCBs(simpleProfileCBs_t *appCallbacks);
/*
* SimpleProfile_SetParameter - Set a Simple GATT Profile parameter.
*
* param - Profile parameter ID
* len - length of data to right
* value - pointer to data to write. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*/
extern bStatus_t SimpleProfile_SetParameter(uint8_t param, uint8_t len, void *value);
/*
* SimpleProfile_GetParameter - Get a Simple GATT Profile parameter.
*
* param - Profile parameter ID
* value - pointer to data to write. This is dependent on
* the parameter ID and WILL be cast to the appropriate
* data type (example: data type of uint16_t will be cast to
* uint16_t pointer).
*/
extern bStatus_t SimpleProfile_GetParameter(uint8_t param, void *value);
/*
* simpleProfile_Notify - Send notification.
*
* connHandle - connect handle
* pNoti - pointer to structure to notify.
*/
extern bStatus_t simpleProfile_Notify(uint16_t connHandle, attHandleValueNoti_t *pNoti);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,82 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : HAL.h
* Author : WCH
* Version : V1.0
* Date : 2016/05/05
* 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 __HAL_H
#define __HAL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
#include "RTC.h"
#include "SLEEP.h"
#include "KEY.h"
#include "LED.h"
/* hal task Event */
#define LED_BLINK_EVENT 0x0001
#define HAL_KEY_EVENT 0x0002
#define HAL_REG_INIT_EVENT 0x2000
#define HAL_TEST_EVENT 0x4000
/*********************************************************************
* GLOBAL VARIABLES
*/
extern tmosTaskID halTaskID;
/*********************************************************************
* GLOBAL FUNCTIONS
*/
/**
* @brief Hardware initialization
*/
extern void HAL_Init(void);
/**
* @brief HAL processing
*
* @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.
*/
extern tmosEvents HAL_ProcessEvent(tmosTaskID task_id, tmosEvents events);
/**
* @brief Initialization of the BLE library
*/
extern void WCHBLE_Init(void);
/**
* @brief Get the internal temperature sampling value.
* If the ADC interrupt sampling is used,
* the interrupt is temporarily shielded in this function.
*
* @return Internal temperature sampling value.
*/
extern uint16_t HAL_GetInterTempValue(void);
/**
* @brief Internal 32K calibration
*/
extern void Lib_Calibration_LSI(void);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,112 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : KEY.h
* Author : WCH
* Version : V1.0
* Date : 2016/04/12
* 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 __KEY_H
#define __KEY_H
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************************************************************
* MACROS
**************************************************************************************************/
#define HAL_KEY_POLLING_VALUE 100
/* Switches (keys) */
#define HAL_KEY_SW_1 0x01 // key1
#define HAL_KEY_SW_2 0x02 // key2
#define HAL_KEY_SW_3 0x04 // key3
#define HAL_KEY_SW_4 0x08 // key4
/* Key definition */
/* 1 - KEY */
#define KEY1_PCENR (RCC_APB2Periph_GPIOB)
#define KEY2_PCENR ()
#define KEY3_PCENR ()
#define KEY4_PCENR ()
#define KEY1_GPIO (GPIOB)
#define KEY2_GPIO ()
#define KEY3_GPIO ()
#define KEY4_GPIO ()
#define KEY1_BV BV(13)
#define KEY2_BV ()
#define KEY3_BV ()
#define KEY4_BV ()
#define KEY1_IN (GPIO_ReadInputDataBit(KEY1_GPIO, KEY1_BV)==0)
#define KEY2_IN ()
#define KEY3_IN ()
#define KEY4_IN ()
#define HAL_PUSH_BUTTON1() (KEY1_IN) //Add custom button
#define HAL_PUSH_BUTTON2() (0)
#define HAL_PUSH_BUTTON3() (0)
#define HAL_PUSH_BUTTON4() (0)
/**************************************************************************************************
* TYPEDEFS
**************************************************************************************************/
typedef void (*halKeyCBack_t)(uint8_t keys);
typedef struct
{
uint8_t keys; // keys
} keyChange_t;
/**************************************************************************************************
* GLOBAL VARIABLES
**************************************************************************************************/
/*********************************************************************
* FUNCTIONS
*/
/**
* @brief Initialize the Key Service
*/
void HAL_KeyInit(void);
/**
* @brief This is for internal used by hal_driver
*/
void HAL_KeyPoll(void);
/**
* @brief Configure the Key serivce
*
* @param cback - pointer to the CallBack function
*/
void HalKeyConfig(const halKeyCBack_t cback);
/**
* @brief Read the Key callback
*/
void HalKeyCallback(uint8_t keys);
/**
* @brief Read the Key status
*/
uint8_t HalKeyRead(void);
/**************************************************************************************************
**************************************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,133 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : LED.h
* Author : WCH
* Version : V1.0
* Date : 2016/04/12
* 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 __LED_H
#define __LED_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* CONSTANTS
*/
/* LEDS - The LED number is the same as the bit position */
#define HAL_LED_1 0x01
#define HAL_LED_2 0x02
#define HAL_LED_3 0x04
#define HAL_LED_4 0x08
#define HAL_LED_ALL (HAL_LED_1 | HAL_LED_2 | HAL_LED_3 | HAL_LED_4)
/* Modes */
#define HAL_LED_MODE_OFF 0x00
#define HAL_LED_MODE_ON 0x01
#define HAL_LED_MODE_BLINK 0x02
#define HAL_LED_MODE_FLASH 0x04
#define HAL_LED_MODE_TOGGLE 0x08
/* Defaults */
#define HAL_LED_DEFAULT_MAX_LEDS 4
#define HAL_LED_DEFAULT_DUTY_CYCLE 5
#define HAL_LED_DEFAULT_FLASH_COUNT 50
#define HAL_LED_DEFAULT_FLASH_TIME 1000
/*********************************************************************
* TYPEDEFS
*/
/* Connect an LED to monitor the progress of the demo program, the low-level LED is on */
/* 1 - LED */
#define LED1_PCENR (RCC_APB2Periph_GPIOB)
#define LED2_PCENR
#define LED3_PCENR
#define LED1_GPIO (GPIOB)
#define LED2_GPIO
#define LED3_GPIO
#define LED1_BV BV(15)
#define LED2_BV
#define LED3_BV
#define HAL_TURN_OFF_LED1() (GPIO_WriteBit(LED1_GPIO, LED1_BV, Bit_SET))
#define HAL_TURN_OFF_LED2()
#define HAL_TURN_OFF_LED3()
#define HAL_TURN_OFF_LED4()
#define HAL_TURN_ON_LED1() (GPIO_WriteBit(LED1_GPIO, LED1_BV, Bit_RESET))
#define HAL_TURN_ON_LED2()
#define HAL_TURN_ON_LED3()
#define HAL_TURN_ON_LED4()
#define HAL_STATE_LED1() 0
#define HAL_STATE_LED2() 0
#define HAL_STATE_LED3() 0
#define HAL_STATE_LED4() 0
/*********************************************************************
* GLOBAL VARIABLES
*/
/**
* @brief Initialize LED Service.
*/
void HAL_LedInit(void);
/**
* @brief update time LED Service.
*/
void HalLedUpdate(void);
/**
* @brief Turn ON/OFF/TOGGLE given LEDs
*
* @param led - bit mask value of leds to be turned ON/OFF/TOGGLE
* @param mode - BLINK, FLASH, TOGGLE, ON, OFF
*/
extern uint8_t HalLedSet(uint8_t led, uint8_t mode);
/**
* @brief Blink the leds
*
* @param led - bit mask value of leds to be turned ON/OFF/TOGGLE
* @param numBlinks - number of blinks
* @param percent - the percentage in each period where the led will be on
* @param period - length of each cycle in milliseconds
*/
extern void HalLedBlink(uint8_t leds, uint8_t cnt, uint8_t duty, uint16_t time);
/**
* @brief Put LEDs in sleep state - store current values
*/
extern void HalLedEnterSleep(void);
/**
* @brief Retore LEDs from sleep state
*/
extern void HalLedExitSleep(void);
/**
* @brief Return LED state
*/
extern uint8_t HalLedGetState(void);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,40 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : RTC.h
* Author : WCH
* Version : V1.0
* Date : 2016/04/12
* 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 __RTC_H
#define __RTC_H
#ifdef __cplusplus
extern "C" {
#endif
extern volatile uint32_t RTCTigFlag;
/**
* @brief Initialize time Service.
*/
void HAL_TimeInit(void);
/**
* @brief Configure RTC trigger time
*
* @param time - Trigger time.
*/
extern void RTC_SetTignTime(uint32_t time);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,50 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : SLEEP.h
* Author : WCH
* Version : V1.0
* Date : 2018/11/12
* 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 __SLEEP_H
#define __SLEEP_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* FUNCTIONS
*/
/**
* @brief Configure sleep Wake-up source - RTC wake up, trigger mode
*/
extern void HAL_SleepInit(void);
/**
* @brief Start sleep
*
* @param time - Wake-up time (RTC absolute value)
*
* @return state.
*/
extern uint32_t BLE_LowPower(uint32_t time);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,133 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : app_drv_fifo.h
* Author : WCH
* Version : V1.1
* Date : 2022/01/19
* 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 __APP_DRV_FIFO_H__
#define __APP_DRV_FIFO_H__
#include <stdbool.h>
#include <stdint.h>
#ifndef BV
#define BV(n) (1 << (n))
#endif
#ifndef BF
#define BF(x, b, s) (((x) & (b)) >> (s))
#endif
#ifndef MIN
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif
#ifndef MAX
#define MAX(n, m) (((n) < (m)) ? (m) : (n))
#endif
#ifndef ABS
#define ABS(n) (((n) < 0) ? -(n) : (n))
#endif
typedef enum
{
APP_DRV_FIFO_RESULT_SUCCESS = 0,
APP_DRV_FIFO_RESULT_LENGTH_ERROR,
APP_DRV_FIFO_RESULT_NOT_FOUND,
APP_DRV_FIFO_RESULT_NOT_MEM,
APP_DRV_FIFO_RESULT_NULL,
} app_drv_fifo_result_t;
#ifndef NULL
#define NULL 0
#endif
/*!
* FIFO structure
*/
typedef struct Fifo_s
{
uint16_t begin;
uint16_t end;
uint8_t *data;
uint16_t size;
uint16_t size_mask;
} app_drv_fifo_t;
//__inline uint16_t app_drv_fifo_length(app_drv_fifo_t *fifo);
uint16_t app_drv_fifo_length(app_drv_fifo_t *fifo);
/*!
* Initializes the FIFO structure
*
* \param [IN] fifo Pointer to the FIFO object
* \param [IN] buffer Buffer to be used as FIFO
* \param [IN] size size of the buffer
*/
app_drv_fifo_result_t
app_drv_fifo_init(app_drv_fifo_t *fifo, uint8_t *buffer, uint16_t buffer_size);
/*!
* Pushes data to the FIFO
*
* \param [IN] fifo Pointer to the FIFO object
* \param [IN] data data to be pushed into the FIFO
*/
void app_drv_fifo_push(app_drv_fifo_t *fifo, uint8_t data);
/*!
* Pops data from the FIFO
*
* \param [IN] fifo Pointer to the FIFO object
* \retval data data popped from the FIFO
*/
uint8_t app_drv_fifo_pop(app_drv_fifo_t *fifo);
/*!
* Flushes the FIFO
*
* \param [IN] fifo Pointer to the FIFO object
*/
void app_drv_fifo_flush(app_drv_fifo_t *fifo);
/*!
* Checks if the FIFO is empty
*
* \param [IN] fifo Pointer to the FIFO object
* \retval isEmpty true: FIFO is empty, false FIFO is not empty
*/
bool app_drv_fifo_is_empty(app_drv_fifo_t *fifo);
/*!
* Checks if the FIFO is full
*
* \param [IN] fifo Pointer to the FIFO object
* \retval isFull true: FIFO is full, false FIFO is not full
*/
bool app_drv_fifo_is_full(app_drv_fifo_t *fifo);
app_drv_fifo_result_t
app_drv_fifo_write(app_drv_fifo_t *fifo, uint8_t *data,
uint16_t *p_write_length);
app_drv_fifo_result_t
app_drv_fifo_write_from_same_addr(app_drv_fifo_t *fifo, uint8_t *data,
uint16_t write_length);
app_drv_fifo_result_t
app_drv_fifo_read(app_drv_fifo_t *fifo, uint8_t *data, uint16_t *p_read_length);
app_drv_fifo_result_t
app_drv_fifo_read_to_same_addr(app_drv_fifo_t *fifo, uint8_t *data,
uint16_t read_length);
#endif // __APP_DRV_FIFO_H__

View File

@ -0,0 +1,66 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : app_uart.h
* Author : WCH
* Version : V1.0
* Date : 2018/12/11
* 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 app_uart_H
#define app_uart_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* INCLUDES
*/
#include "app_drv_fifo.h"
#include "ble_uart_service.h"
/*********************************************************************
* CONSTANTS
*/
extern uint8_t to_test_buffer[BLE_BUFF_MAX_LEN - 4 - 3];
extern app_drv_fifo_t app_uart_tx_fifo;
extern app_drv_fifo_t app_uart_rx_fifo;
//interupt uart rx flag ,clear at main loop
extern bool uart_rx_flag;
//for interrupt rx blcak hole ,when uart rx fifo full
extern uint8_t for_uart_rx_black_hole;
//fifo length less that MTU-3, retry times
extern uint32_t uart_to_ble_send_evt_cnt;
/*********************************************************************
* MACROS
*/
/*********************************************************************
* FUNCTIONS
*/
extern void app_uart_process(void);
extern void app_uart_init(void);
extern void on_bleuartServiceEvt(uint16_t connection_handle, ble_uart_evt_t *p_evt);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,70 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : simpleGATTprofile.h
* Author : WCH
* Version : V1.1
* Date : 2022/01/19
* 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_UART_SERVICE_H
#define _BLE_UART_SERVICE_H
#ifdef __cplusplus
extern "C" {
#endif
//#include "att.h"
#include "stdint.h"
#define BLE_UART_RX_BUFF_SIZE 1
typedef enum
{
BLE_UART_EVT_TX_NOTI_DISABLED = 1,
BLE_UART_EVT_TX_NOTI_ENABLED,
BLE_UART_EVT_BLE_DATA_RECIEVED,
} ble_uart_evt_type_t;
typedef struct
{
uint8_t const *p_data; /**< A pointer to the buffer with received data. */
uint16_t length; /**< Length of received data. */
} ble_uart_evt_rx_data_t;
typedef struct
{
ble_uart_evt_type_t type;
ble_uart_evt_rx_data_t data;
} ble_uart_evt_t;
typedef void (*ble_uart_ProfileChangeCB_t)(uint16_t connection_handle, ble_uart_evt_t *p_evt);
/*********************************************************************
* API FUNCTIONS
*/
/*
* ble_uart_AddService- Initializes the raw pass GATT Profile service by registering
* GATT attributes with the GATT server.
*
* @param services - services to add. This is a bit map and can
* contain more than one service.
*/
extern bStatus_t ble_uart_add_service(ble_uart_ProfileChangeCB_t cb);
extern uint8_t ble_uart_notify_is_ready(uint16_t connHandle);
extern bStatus_t ble_uart_notify(uint16_t connHandle, attHandleValueNoti_t *pNoti, uint8_t taskId);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* _BLE_UART_SERVICE_H */

View File

@ -0,0 +1,137 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : CONFIG.h
* Author : WCH
* Version : V1.2
* Date : 2022/01/18
* Description : Configuration description and default value,
* it is recommended to modify the current value in the
* pre-processing of the engineering configuration
*********************************************************************************
* 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 __CONFIG_H
#define __CONFIG_H
#define ID_CH32V208 0x0208
#define CHIP_ID ID_CH32V208
#ifdef WCHBLE_ROM
#include "WCHBLE_ROM.H"
#else
#include "wchble.h"
#endif
#include "ch32v20x.h"
/*********************************************************************
MAC
BLE_MAC - Mac地址 ( :FALSE - 使Mac地址 )main.c修改Mac地址定义
SLEEP
HAL_SLEEP - ( :FALSE )
WAKE_UP_MAX_TIME_US -
- 45
- 5
TEMPERATION
TEM_SAMPLE - 10ms( :TRUE )
CALIBRATION
BLE_CALIBRATION_ENABLE - 10ms( :TRUE )
BLE_CALIBRATION_PERIOD - ms( :120000 )
SNV
BLE_SNV - SNV功能( :TRUE )
BLE_SNV_ADDR - SNV信息保存地址使data flash最后( :0x77E00 )
BLE_SNV_NUM - SNV信息存储扇区数量等于可存储的绑定数量( :3 )
- SNVNum参数Lib_Write_Flash函数内擦除的flash大小SNVBlock*SNVNum
RTC
CLK_OSC32K - RTC时钟选择使32K( 0 (32768Hz):1(32000Hz)2(32768Hz) )
MEMORY
BLE_MEMHEAP_SIZE - 使RAM大小6K ( :(1024*6) )
DATA
BLE_BUFF_MAX_LEN - ( :27 (ATT_MTU=23)[27~251] )
BLE_BUFF_NUM - ( :5 )
BLE_TX_NUM_EVENT - ( :1 )
BLE_TX_POWER - ( :LL_TX_POWEER_0_DBM (0dBm) )
MULTICONN
PERIPHERAL_MAX_CONNECTION - ( :1 )
CENTRAL_MAX_CONNECTION - ( :3 )
**********************************************************************/
/*********************************************************************
*
*/
#ifndef BLE_MAC
#define BLE_MAC FALSE
#endif
#ifndef HAL_SLEEP
#define HAL_SLEEP FALSE
#endif
#ifndef WAKE_UP_MAX_TIME_US
#define WAKE_UP_MAX_TIME_US 2400
#endif
#ifndef HAL_KEY
#define HAL_KEY FALSE
#endif
#ifndef HAL_LED
#define HAL_LED FALSE
#endif
#ifndef TEM_SAMPLE
#define TEM_SAMPLE TRUE
#endif
#ifndef BLE_CALIBRATION_ENABLE
#define BLE_CALIBRATION_ENABLE TRUE
#endif
#ifndef BLE_CALIBRATION_PERIOD
#define BLE_CALIBRATION_PERIOD 120000
#endif
#ifndef BLE_SNV
#define BLE_SNV TRUE
#endif
#ifndef BLE_SNV_ADDR
#define BLE_SNV_ADDR 0x08077C00
#endif
#ifndef BLE_SNV_NUM
#define BLE_SNV_NUM 3
#endif
#ifndef CLK_OSC32K
#define CLK_OSC32K 1 // 该项请勿在此修改必须在工程配置里的预处理中修改如包含主机角色必须使用外部32K
#endif
#ifndef BLE_MEMHEAP_SIZE
#define BLE_MEMHEAP_SIZE (1024*7)
#endif
#ifndef BLE_BUFF_MAX_LEN
#define BLE_BUFF_MAX_LEN 27
#endif
#ifndef BLE_BUFF_NUM
#define BLE_BUFF_NUM 5
#endif
#ifndef BLE_TX_NUM_EVENT
#define BLE_TX_NUM_EVENT 1
#endif
#ifndef BLE_TX_POWER
#define BLE_TX_POWER LL_TX_POWEER_0_DBM
#endif
#ifndef PERIPHERAL_MAX_CONNECTION
#define PERIPHERAL_MAX_CONNECTION 1
#endif
#ifndef CENTRAL_MAX_CONNECTION
#define CENTRAL_MAX_CONNECTION 3
#endif
extern uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
extern const uint8_t MacAddr[6];
#endif

View File

@ -0,0 +1,68 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : peripheral.h
* Author : WCH
* Version : V1.0
* Date : 2018/12/11
* 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 PERIPHERAL_H
#define PERIPHERAL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************
* INCLUDES
*/
/*********************************************************************
* CONSTANTS
*/
// Peripheral Task Events
#define SBP_START_DEVICE_EVT 0x0001
#define SBP_READ_RSSI_EVT 0x0004
#define SBP_PARAM_UPDATE_EVT 0x0008
#define UART_TO_BLE_SEND_EVT 0x0010
/*********************************************************************
* MACROS
*/
typedef struct
{
uint16_t connHandle; // Connection handle of current connection
uint16_t connInterval;
uint16_t connSlaveLatency;
uint16_t connTimeout;
} peripheralConnItem_t;
extern uint8_t Peripheral_TaskID;
/*********************************************************************
* FUNCTIONS
*/
/*
* Task Initialization for the BLE Application
*/
extern void Peripheral_Init(void);
/*
* Task Event Processor for the BLE Application
*/
extern uint16_t Peripheral_ProcessEvent(uint8_t task_id, uint16_t events);
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : KEY.c
* Author : WCH
* Version : V1.2
* Date : 2022/01/18
* 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.
*******************************************************************************/
/******************************************************************************/
/* Header file contains */
#include "../../inc/HAL.h"
/**************************************************************************************************
* GLOBAL VARIABLES
**************************************************************************************************/
static uint8_t halKeySavedKeys; /* Keep the last state of the button to query whether there is a key value change */
/**************************************************************************************************
* FUNCTIONS - Local
**************************************************************************************************/
static halKeyCBack_t pHalKeyProcessFunction; /* callback function */
/**************************************************************************************************
* @fn HAL_KeyInit
*
* @brief Initilize Key Service
*
* @param none
*
* @return None
**************************************************************************************************/
void HAL_KeyInit(void)
{
/* Initialize previous key to 0 */
halKeySavedKeys = 0;
/* Initialize callback function */
pHalKeyProcessFunction = NULL;
RCC_APB2PeriphClockCmd(KEY1_PCENR, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = KEY1_BV;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY1_GPIO, &GPIO_InitStructure);
}
/**************************************************************************************************
* @fn HalKeyConfig
*
* @brief Configure the Key serivce
*
* @param cback - pointer to the CallBack function
*
* @return None
**************************************************************************************************/
void HalKeyConfig(halKeyCBack_t cback)
{
/* Register the callback fucntion */
pHalKeyProcessFunction = cback;
tmos_start_task(halTaskID, HAL_KEY_EVENT, HAL_KEY_POLLING_VALUE); /* Kick off polling */
}
/**************************************************************************************************
* @fn HalKeyRead
*
* @brief Read the current value of a key
*
* @param None
*
* @return keys - current keys status
**************************************************************************************************/
uint8_t HalKeyRead(void)
{
uint8_t keys = 0;
if(HAL_PUSH_BUTTON1())
{ //Read button 1
keys |= HAL_KEY_SW_1;
}
if(HAL_PUSH_BUTTON2())
{ //Read button 1
keys |= HAL_KEY_SW_2;
}
if(HAL_PUSH_BUTTON3())
{ //Read button 1
keys |= HAL_KEY_SW_3;
}
if(HAL_PUSH_BUTTON4())
{ //Read button 1
keys |= HAL_KEY_SW_4;
}
return keys;
}
/**************************************************************************************************
* @fn HAL_KeyPoll
*
* @brief Called by hal_driver to poll the keys
*
* @param None
*
* @return None
**************************************************************************************************/
void HAL_KeyPoll(void)
{
uint8_t keys = 0;
if(HAL_PUSH_BUTTON1())
{
keys |= HAL_KEY_SW_1;
}
if(HAL_PUSH_BUTTON2())
{
keys |= HAL_KEY_SW_2;
}
if(HAL_PUSH_BUTTON3())
{
keys |= HAL_KEY_SW_3;
}
if(HAL_PUSH_BUTTON4())
{
keys |= HAL_KEY_SW_4;
}
if(keys == halKeySavedKeys)
{ /* Exit - since no keys have changed */
return;
}
halKeySavedKeys = keys; /* Store the current keys for comparation next time */
/* Invoke Callback if new keys were depressed */
if(keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction)(keys);
}
}
/******************************** endfile @ key ******************************/

View File

@ -0,0 +1,366 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : LED.c
* Author : WCH
* Version : V1.2
* Date : 2022/01/18
* 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.
*******************************************************************************/
/******************************************************************************/
/* Header file contains */
#include "../../inc/HAL.h"
/* LED control structure */
typedef struct
{
uint8_t mode; /* Operation mode */
uint8_t todo; /* Blink cycles left */
uint8_t onPct; /* On cycle percentage */
uint16_t time; /* On/off cycle time (msec) */
uint32_t next; /* Time for next change */
} HalLedControl_t;
typedef struct
{
HalLedControl_t HalLedControlTable[HAL_LED_DEFAULT_MAX_LEDS];
uint8_t sleepActive;
} HalLedStatus_t;
/***************************************************************************************************
* GLOBAL VARIABLES
***************************************************************************************************/
static uint8_t HalLedState; // LED state at last set/clr/blink update
static uint8_t preBlinkState; // Original State before going to blink mode
// bit 0, 1, 2, 3 represent led 0, 1, 2, 3
static HalLedStatus_t HalLedStatusControl;
/***************************************************************************************************
* LOCAL FUNCTION
***************************************************************************************************/
void HalLedOnOff(uint8_t leds, uint8_t mode);
/***************************************************************************************************
* FUNCTIONS - API
***************************************************************************************************/
/*********************************************************************
* @fn HAL_LedInit
*
* @brief Initialize LED Service
*
* @return none
*/
void HAL_LedInit(void)
{
/* Initialize all LEDs to OFF */
RCC_APB2PeriphClockCmd(LED1_PCENR, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = LED1_BV;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED1_GPIO, &GPIO_InitStructure);
HalLedSet(HAL_LED_ALL, HAL_LED_MODE_OFF);
// just test
HalLedBlink(HAL_LED_1, 10, 30, 4000);
/* Initialize sleepActive to FALSE */
HalLedStatusControl.sleepActive = FALSE;
}
/*********************************************************************
* @fn HalLedSet
*
* @brief Turn ON/OFF/TOGGLE given LEDs
*
* @param led - bit mask value of leds to be turned ON/OFF/TOGGLE
* @param mode - BLINK, FLASH, TOGGLE, ON, OFF
*
* @return 0
*/
uint8_t HalLedSet(uint8_t leds, uint8_t mode)
{
uint8_t led;
HalLedControl_t *sts;
switch(mode)
{
case HAL_LED_MODE_BLINK:
{
/* Default blink, 1 time, D% duty cycle */
HalLedBlink(leds, 1, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
break;
}
case HAL_LED_MODE_FLASH:
{
/* Default flash, N times, D% duty cycle */
HalLedBlink(leds, HAL_LED_DEFAULT_FLASH_COUNT, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
break;
}
case HAL_LED_MODE_ON:
case HAL_LED_MODE_OFF:
case HAL_LED_MODE_TOGGLE:
{
led = HAL_LED_1;
leds &= HAL_LED_ALL;
sts = HalLedStatusControl.HalLedControlTable;
while(leds)
{
if(leds & led)
{
if(mode != HAL_LED_MODE_TOGGLE)
{
sts->mode = mode; /* ON or OFF */
}
else
{
sts->mode ^= HAL_LED_MODE_ON; /* Toggle */
}
HalLedOnOff(led, sts->mode);
leds ^= led;
}
led <<= 1;
sts++;
}
break;
}
default:
break;
}
return (0);
}
/*********************************************************************
* @fn HalLedBlink
*
* @brief Blink the leds
*
* @param led - bit mask value of leds to be turned ON/OFF/TOGGLE
* @param numBlinks - number of blinks
* @param percent - the percentage in each period where the led will be on
* @param period - length of each cycle in milliseconds
*
* @return none
*/
void HalLedBlink(uint8_t leds, uint8_t numBlinks, uint8_t percent, uint16_t period)
{
uint8_t led;
HalLedControl_t *sts;
if(leds && percent && period)
{
if(percent < 100)
{
led = HAL_LED_1;
leds &= HAL_LED_ALL;
sts = HalLedStatusControl.HalLedControlTable;
while(leds)
{
if(leds & led)
{
/* Store the current state of the led before going to blinking */
preBlinkState |= (led & HalLedState);
sts->mode = HAL_LED_MODE_OFF; /* Stop previous blink */
sts->time = period; /* Time for one on/off cycle */
sts->onPct = percent; /* % of cycle LED is on */
sts->todo = numBlinks; /* Number of blink cycles */
if(!numBlinks)
{
sts->mode |= HAL_LED_MODE_FLASH; /* Continuous */
}
sts->next = TMOS_GetSystemClock(); /* Start now */
sts->mode |= HAL_LED_MODE_BLINK; /* Enable blinking */
leds ^= led;
}
led <<= 1;
sts++;
}
tmos_start_task(halTaskID, LED_BLINK_EVENT, 0);
}
else
{
HalLedSet(leds, HAL_LED_MODE_ON); /* >= 100%, turn on */
}
}
else
{
HalLedSet(leds, HAL_LED_MODE_OFF); /* No on time, turn off */
}
}
/*********************************************************************
* @fn HalLedUpdate
*
* @brief Update leds to work with blink
*
* @return none
*/
void HalLedUpdate(void)
{
uint8_t led, pct, leds;
uint16_t next, wait;
uint32_t time;
HalLedControl_t *sts;
next = 0;
led = HAL_LED_1;
leds = HAL_LED_ALL;
sts = HalLedStatusControl.HalLedControlTable;
/* Check if sleep is active or not */
if(!HalLedStatusControl.sleepActive)
{
while(leds)
{
if(leds & led)
{
if(sts->mode & HAL_LED_MODE_BLINK)
{
time = TMOS_GetSystemClock();
if(time >= sts->next)
{
if(sts->mode & HAL_LED_MODE_ON)
{
pct = 100 - sts->onPct; /* Percentage of cycle for off */
sts->mode &= ~HAL_LED_MODE_ON; /* Say it's not on */
HalLedOnOff(led, HAL_LED_MODE_OFF); /* Turn it off */
if(!(sts->mode & HAL_LED_MODE_FLASH))
{
if(sts->todo != 0xff)
{
sts->todo--; /* Not continuous, reduce count */
}
if(!sts->todo)
{
sts->mode ^= HAL_LED_MODE_BLINK; /* No more blinks */
}
}
}
else
{
pct = sts->onPct; /* Percentage of cycle for on */
sts->mode |= HAL_LED_MODE_ON; /* Say it's on */
HalLedOnOff(led, HAL_LED_MODE_ON); /* Turn it on */
}
if(sts->mode & HAL_LED_MODE_BLINK)
{
wait = (((uint32_t)pct * (uint32_t)sts->time) / 100);
sts->next = time + wait;
}
else
{
/* no more blink, no more wait */
wait = 0;
/* After blinking, set the LED back to the state before it blinks */
HalLedSet(led, ((preBlinkState & led) != 0) ? HAL_LED_MODE_ON : HAL_LED_MODE_OFF);
/* Clear the saved bit */
preBlinkState &= (led ^ 0xFF);
}
}
else
{
wait = sts->next - time; /* Time left */
}
if(!next || (wait && (wait < next)))
{
next = wait;
}
}
leds ^= led;
}
led <<= 1;
sts++;
}
if(next)
{
tmos_start_task(halTaskID, LED_BLINK_EVENT, next); /* Schedule event */
}
}
}
/*********************************************************************
* @fn HalLedOnOff
*
* @brief Turns specified LED ON or OFF
*
* @param led - LED bit mask
* @param mode - LED_ON,LED_OFF,
*
* @return none
*/
void HalLedOnOff(uint8_t leds, uint8_t mode)
{
if(leds & HAL_LED_1)
{
if(mode == HAL_LED_MODE_ON)
{
HAL_TURN_ON_LED1();
}
else
{
HAL_TURN_OFF_LED1();
}
}
if(leds & HAL_LED_2)
{
if(mode == HAL_LED_MODE_ON)
{
HAL_TURN_ON_LED2();
}
else
{
HAL_TURN_OFF_LED2();
}
}
if(leds & HAL_LED_3)
{
if(mode == HAL_LED_MODE_ON)
{
HAL_TURN_ON_LED3();
}
else
{
HAL_TURN_OFF_LED3();
}
}
if(leds & HAL_LED_4)
{
if(mode == HAL_LED_MODE_ON)
{
HAL_TURN_ON_LED4();
}
else
{
HAL_TURN_OFF_LED4();
}
}
/* Remember current state */
if(mode)
{
HalLedState |= leds;
}
else
{
HalLedState &= (leds ^ 0xFF);
}
}
/***************************************************************************************************
* @fn HalGetLedState
*
* @brief Dim LED2 - Dim (set level) of LED2
*
* @return led state
*/
uint8_t HalLedGetState()
{
return HalLedState;
}
/******************************** endfile @ led ******************************/

View File

@ -0,0 +1,328 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : MCU.c
* Author : WCH
* Version : V1.2
* Date : 2022/01/18
* Description : HAL task processing function and BLE and hardware initialization
*********************************************************************************
* 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 "../../inc/HAL.h"
#include "string.h"
#include "xs_base.h"
tmosTaskID halTaskID;
uint32_t g_LLE_IRQLibHandlerLocation;
/*******************************************************************************
* @fn Lib_Calibration_LSI
*
* @brief Internal 32K calibration
*
* @param None.
*
* @return None.
*/
void Lib_Calibration_LSI(void)
{
Calibration_LSI(Level_64);
}
#if(defined(BLE_SNV)) && (BLE_SNV == TRUE)
/*******************************************************************************
* @fn Lib_Read_Flash
*
* @brief Callback function used for BLE lib.
*
* @param addr.
* @param num.
* @param pBuf.
*
* @return None.
*/
uint32_t Lib_Read_Flash(uint32_t addr, uint32_t num, uint32_t *pBuf)
{
tmos_memcpy(pBuf, (uint32_t*)addr, num*4);
return 0;
}
/*******************************************************************************
* @fn Lib_Write_Flash
*
* @brief Callback function used for BLE lib.
*
* @param addr.
* @param num.
* @param pBuf.
*
* @return None.
*/
uint32_t Lib_Write_Flash(uint32_t addr, uint32_t num, uint32_t *pBuf)
{
FLASH_Unlock_Fast();
FLASH_ErasePage_Fast( addr );
FLASH_ProgramPage_Fast( addr, pBuf);
FLASH_Lock_Fast();
Delay_Us(1);
return 0;
}
#endif
/*******************************************************************************
* @fn WCHBLE_Init
*
* @brief BLE library initialization
*
* @param None.
*
* @return None.
*/
void WCHBLE_Init(void)
{
uint8_t i;
bleConfig_t cfg;
g_LLE_IRQLibHandlerLocation = (uint32_t)LLE_IRQLibHandler;
if(!tmos_memcmp(VER_LIB, VER_FILE, strlen(VER_FILE)))
{
PRINT("head file error...\n");
while(1);
}
// 32M crystal capacitance and current
OSC->HSE_CAL_CTRL &= ~(0x07<<28);
OSC->HSE_CAL_CTRL |= 0x03<<28;
OSC->HSE_CAL_CTRL |= 3<<24;
tmos_memset(&cfg, 0, sizeof(bleConfig_t));
cfg.MEMAddr = (uint32_t)MEM_BUF;
cfg.MEMLen = (uint32_t)BLE_MEMHEAP_SIZE;
cfg.BufMaxLen = (uint32_t)BLE_BUFF_MAX_LEN;
cfg.BufNumber = (uint32_t)BLE_BUFF_NUM;
cfg.TxNumEvent = (uint32_t)BLE_TX_NUM_EVENT;
cfg.TxPower = (uint32_t)BLE_TX_POWER;
#if(defined(BLE_SNV)) && (BLE_SNV == TRUE)
cfg.SNVAddr = (uint32_t)BLE_SNV_ADDR;
cfg.SNVNum = (uint32_t)BLE_SNV_NUM;
cfg.readFlashCB = Lib_Read_Flash;
cfg.writeFlashCB = Lib_Write_Flash;
#endif
cfg.ClockFrequency = CAB_LSIFQ/2;
#if(CLK_OSC32K==0)
cfg.ClockAccuracy = 50;
#else
cfg.ClockAccuracy = 1000;
#endif
cfg.ConnectNumber = (PERIPHERAL_MAX_CONNECTION & 3) | (CENTRAL_MAX_CONNECTION << 2);
#if(defined TEM_SAMPLE) && (TEM_SAMPLE == TRUE)
// Calibrate RF and internal RC according to temperature changes (greater than 7 degrees Celsius)
cfg.tsCB = HAL_GetInterTempValue;
#if(CLK_OSC32K)
cfg.rcCB = Lib_Calibration_LSI; // Internal 32K clock calibration
#endif
#endif
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
cfg.idleCB = BLE_LowPower; // Enable sleep
#endif
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
for(i = 0; i < 6; i++)
{
cfg.MacAddr[i] = MacAddr[5 - i];
}
#else
{
uint8_t MacAddr[6];
FLASH_GetMACAddress(MacAddr);
for(i = 0; i < 6; i++)
{
cfg.MacAddr[i] = MacAddr[i]; // Use chip mac address
}
}
#endif
if(!cfg.MEMAddr || cfg.MEMLen < 4 * 1024)
{
while(1);
}
i = BLE_LibInit(&cfg);
if(i)
{
KPrintf("LIB init error code: %x ...\n", i);
while(1);
}
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE );
NVIC_EnableIRQ( BB_IRQn );
NVIC_EnableIRQ( LLE_IRQn );
KPrintf("WCHBLE_LibInit Success\n");
}
/*******************************************************************************
* @fn HAL_ProcessEvent
*
* @brief HAL processing
*
* @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.
*/
tmosEvents HAL_ProcessEvent(tmosTaskID task_id, tmosEvents events)
{
uint8_t *msgPtr;
if(events & SYS_EVENT_MSG)
{
/**
* Process the HAL layer message, call tmos_msg_receive to read the message,
* and delete the message after processing.
*/
msgPtr = tmos_msg_receive(task_id);
if(msgPtr)
{
/* De-allocate */
tmos_msg_deallocate(msgPtr);
}
return events ^ SYS_EVENT_MSG;
}
if(events & LED_BLINK_EVENT)
{
#if(defined HAL_LED) && (HAL_LED == TRUE)
HalLedUpdate();
#endif // HAL_LED
return events ^ LED_BLINK_EVENT;
}
if(events & HAL_KEY_EVENT)
{
#if(defined HAL_KEY) && (HAL_KEY == TRUE)
HAL_KeyPoll(); /* Check for keys */
tmos_start_task(halTaskID, HAL_KEY_EVENT, MS1_TO_SYSTEM_TIME(100));
return events ^ HAL_KEY_EVENT;
#endif
}
if(events & HAL_REG_INIT_EVENT)
{
#if(defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE) // Calibration tasks, a single time is less than 10ms
BLE_RegInit(); // Calibrate RF
#if(CLK_OSC32K)
Lib_Calibration_LSI(); // Calibrate internal RC
#endif
tmos_start_task(halTaskID, HAL_REG_INIT_EVENT, MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD));
return events ^ HAL_REG_INIT_EVENT;
#endif
}
if(events & HAL_TEST_EVENT)
{
PRINT("* \n");
tmos_start_task(halTaskID, HAL_TEST_EVENT, MS1_TO_SYSTEM_TIME(1000));
return events ^ HAL_TEST_EVENT;
}
return 0;
}
/*******************************************************************************
* @fn HAL_Init
*
* @brief
*
* @param None.
*
* @return None.
*/
void HAL_Init()
{
halTaskID = TMOS_ProcessEventRegister(HAL_ProcessEvent);
HAL_TimeInit();
#if(defined HAL_SLEEP) && (HAL_SLEEP == TRUE)
HAL_SleepInit();
#endif
#if(defined HAL_LED) && (HAL_LED == TRUE)
HAL_LedInit();
#endif
#if(defined HAL_KEY) && (HAL_KEY == TRUE)
HAL_KeyInit();
#endif
#if(defined BLE_CALIBRATION_ENABLE) && (BLE_CALIBRATION_ENABLE == TRUE)
// Add a calibration task, and a single calibration takes less than 10ms
tmos_start_task(halTaskID, HAL_REG_INIT_EVENT, MS1_TO_SYSTEM_TIME(BLE_CALIBRATION_PERIOD));
#endif
// tmos_start_task(halTaskID, HAL_TEST_EVENT, MS1_TO_SYSTEM_TIME(1000)); // Add a test task
}
/*******************************************************************************
* @fn HAL_GetInterTempValue
*
* @brief Get the internal temperature sampling value, if the ADC interrupt sampling is used,
* it is necessary to temporarily shield the interrupt in this function.
*
* @return Internal temperature sampling value.
*/
uint16_t HAL_GetInterTempValue(void)
{
uint32_t rcc_apb2pcenr, rcc_cfgr0, adc1_ctrl1, adc1_ctrl2, adc1_rsqr1, adc1_rsqr2, adc1_rsqr3, adc1_samptr1, adc1_samptr2;
uint32_t adc1_iofr1, adc1_iofr2, adc1_iofr3, adc1_iofr4, adc1_wdhtr, adc1_wdltr, adc1_isqr;
ADC_InitTypeDef ADC_InitStructure = {0};
uint16_t adc_data;
rcc_apb2pcenr = RCC->APB2PCENR;
rcc_cfgr0 = RCC->CFGR0;
adc1_ctrl1 = ADC1->CTLR1;
adc1_ctrl2 = ADC1->CTLR2;
adc1_rsqr1 = ADC1->RSQR1;
adc1_rsqr2 = ADC1->RSQR2;
adc1_rsqr3 = ADC1->RSQR3;
adc1_samptr1 = ADC1->SAMPTR1;
adc1_samptr2 = ADC1->SAMPTR2;
adc1_iofr1 = ADC1->IOFR1;
adc1_iofr2 = ADC1->IOFR2;
adc1_iofr3 = ADC1->IOFR3;
adc1_iofr4 = ADC1->IOFR4;
adc1_wdhtr = ADC1->WDHTR;
adc1_wdltr = ADC1->WDLTR;
adc1_isqr = ADC1->ISQR;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);
ADC_BufferCmd(ADC1, ENABLE); //enable buffer
ADC_TempSensorVrefintCmd(ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 1, ADC_SampleTime_239Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
adc_data = ADC_GetConversionValue(ADC1);
ADC_DeInit(ADC1);
RCC->APB2PCENR = rcc_apb2pcenr;
RCC->CFGR0 = rcc_cfgr0;
ADC1->CTLR1 = adc1_ctrl1;
ADC1->CTLR2 = adc1_ctrl2;
ADC1->RSQR1 = adc1_rsqr1;
ADC1->RSQR2 = adc1_rsqr2;
ADC1->RSQR3 = adc1_rsqr3;
ADC1->SAMPTR1 = adc1_samptr1;
ADC1->SAMPTR2 = adc1_samptr2;
ADC1->IOFR1 = adc1_iofr1;
ADC1->IOFR2 = adc1_iofr2;
ADC1->IOFR3 = adc1_iofr3;
ADC1->IOFR4 = adc1_iofr4;
ADC1->WDHTR = adc1_wdhtr;
ADC1->WDLTR = adc1_wdltr;
ADC1->ISQR = adc1_isqr;
return (adc_data);
}
/******************************** endfile @ mcu ******************************/

View File

@ -0,0 +1,2 @@
SRC_FILES := KEY.c LED.c MCU.c RTC.c SLEEP.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,113 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : RTC.c
* Author : WCH
* Version : V1.2
* Date : 2022/01/18
* Description : RTC configuration and its initialization
*********************************************************************************
* 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 "../../inc/HAL.h"
/*********************************************************************
* CONSTANTS
*/
#define RTC_INIT_TIME_HOUR 0
#define RTC_INIT_TIME_MINUTE 0
#define RTC_INIT_TIME_SECEND 0
/***************************************************
* Global variables
*/
volatile uint32_t RTCTigFlag;
/*******************************************************************************
* @fn RTC_SetTignTime
*
* @brief Configure RTC trigger time
*
* @param time - Trigger time.
*
* @return None.
*/
void RTC_SetTignTime(uint32_t time)
{
RTC_WaitForLastTask();
RTC_SetAlarm(time);
RTC_WaitForLastTask();
RTCTigFlag = 0;
}
/*******************************************************************************
* @fn HAL_Time0Init
*
* @brief System timer initialization
*
* @param None.
*
* @return None.
*/
void HAL_TimeInit(void)
{
uint16_t temp=0;
uint8_t state=0;
bleClockConfig_t conf={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
#if( CLK_OSC32K )
RCC_LSICmd(ENABLE);
RCC_LSEConfig(RCC_LSE_OFF);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
#else
RCC_LSEConfig(RCC_LSE_ON);
/* Check the specified RCC logo position settings or not,
* wait for the low-speed crystal oscillator to be ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
temp++;
Delay_Ms(10);
}
if(temp>=250)
{
printf("time error..\n");
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
#endif
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForLastTask();
RTC_SetPrescaler(1);
RTC_WaitForLastTask();
RTC_SetCounter(0);
RTC_WaitForLastTask();
#if( CLK_OSC32K )
Lib_Calibration_LSI();
#endif
conf.ClockAccuracy = CLK_OSC32K?1000:100;
conf.ClockFrequency = CAB_LSIFQ/2;
conf.ClockMaxCount = 0xFFFFFFFF;
conf.getClockValue = RTC_GetCounter;
state = TMOS_TimerInit( &conf );
if(state)
{
PRINT("TMOS_TimerInit err %x\n",state);
}
}
__attribute__((interrupt()))
void RTCAlarm_IRQHandler(void)
{
RTCTigFlag = 1;
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearITPendingBit(RTC_IT_ALR);
RTC_WaitForLastTask();
}
/******************************** endfile @ time ******************************/

View File

@ -0,0 +1,109 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : SLEEP.c
* Author : WCH
* Version : V1.2
* Date : 2022/01/18
* Description : Sleep configuration and its initialization
*********************************************************************************
* 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 "../../inc/HAL.h"
#include "xs_base.h"
#define US_TO_TICK(us) (uint32_t)((us) / (1000000 / ((CAB_LSIFQ / 2))))
#define SLEEP_PERIOD_MIN_US 200
#define SLEEP_PERIOD_MAX_TICK 0xFFD2393F
#define SLEEP_PERIOD_MIN_TICK US_TO_TICK(SLEEP_PERIOD_MIN_US)
#define HESREADY_TICK US_TO_TICK(WAKE_UP_MAX_TIME_US)
/*******************************************************************************
* @fn BLE_LowPower
*
* @brief
*
* @param time - RTC绝对值
*
* @return state.
*/
uint32_t BLE_LowPower(uint32_t time)
{
KPrintf("%s %d\n", __FUNCTION__, __LINE__);
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
uint32_t current_time;
uint32_t sleep_period;
uint32_t wake_time;
wake_time = time - HESREADY_TICK;
__disable_irq();
current_time = RTC_GetCounter();
sleep_period = wake_time - current_time;
if((sleep_period < SLEEP_PERIOD_MIN_TICK) || (sleep_period > SLEEP_PERIOD_MAX_TICK))
{
__enable_irq();
return 2;
}
RTC_SetTignTime(wake_time);
__enable_irq();
#if(DEBUG == DEBUG_UART1) // To use other serial ports to output printing information, you need to modify this line of code
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{
__NOP();
}
#endif
// LOW POWER-sleep
if(!RTCTigFlag)
{
PWR_EnterSTOPMode_RAM_LV(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
SystemInit();
}
else
{
return 3;
}
#endif
return 0;
}
/*******************************************************************************
* @fn HAL_SleepInit
*
* @brief Configure sleep Wake-up source - RTC wake up, trigger mode
*
* @param None.
*
* @return None.
*/
void HAL_SleepInit(void)
{
#if(defined(HAL_SLEEP)) && (HAL_SLEEP == TRUE)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_ALR, ENABLE);
EXTI_InitTypeDef EXTI_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
}

View File

@ -0,0 +1,3 @@
SRC_FILES := app_drv_fifo.c app_uart.c ble_uart_service.c
SRC_DIR := HAL
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,191 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : app_drv_fifo.c
* Author : WCH
* Version : V1.1
* Date : 2022/01/19
* 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 "../inc/app_drv_fifo.h"
static __inline uint16_t fifo_length(app_drv_fifo_t *fifo)
{
uint16_t tmp = fifo->begin;
return fifo->end - tmp;
}
uint16_t app_drv_fifo_length(app_drv_fifo_t *fifo)
{
return fifo_length(fifo);
}
app_drv_fifo_result_t
app_drv_fifo_init(app_drv_fifo_t *fifo, uint8_t *buffer, uint16_t buffer_size)
{
if(buffer_size == 0)
{
return APP_DRV_FIFO_RESULT_LENGTH_ERROR;
}
if(0 != ((buffer_size) & (buffer_size - 1)))
{
return APP_DRV_FIFO_RESULT_LENGTH_ERROR;
}
fifo->begin = 0;
fifo->end = 0;
fifo->data = buffer;
fifo->size = buffer_size;
fifo->size_mask = buffer_size - 1;
return APP_DRV_FIFO_RESULT_SUCCESS;
}
void app_drv_fifo_push(app_drv_fifo_t *fifo, uint8_t data)
{
fifo->data[fifo->end & fifo->size_mask] = data;
fifo->end++;
}
uint8_t app_drv_fifo_pop(app_drv_fifo_t *fifo)
{
uint8_t data = fifo->data[fifo->begin & fifo->size_mask];
fifo->begin++;
return data;
}
void app_drv_fifo_flush(app_drv_fifo_t *fifo)
{
fifo->begin = 0;
fifo->end = 0;
}
bool app_drv_fifo_is_empty(app_drv_fifo_t *fifo)
{
return (fifo->begin == fifo->end);
}
bool app_drv_fifo_is_full(app_drv_fifo_t *fifo)
{
return (fifo_length(fifo) == fifo->size);
}
app_drv_fifo_result_t
app_drv_fifo_write(app_drv_fifo_t *fifo, uint8_t *data, uint16_t *p_write_length)
{
if(fifo == NULL)
{
return APP_DRV_FIFO_RESULT_NULL;
}
if(p_write_length == NULL)
{
return APP_DRV_FIFO_RESULT_NULL;
}
//PRINT("fifo_length = %d\r\n",fifo_length(fifo));
const uint16_t available_count = fifo->size - fifo_length(fifo);
const uint16_t requested_len = (*p_write_length);
uint16_t index = 0;
uint16_t write_size = MIN(requested_len, available_count);
//PRINT("available_count %d\r\n",available_count);
// Check if the FIFO is FULL.
if(available_count == 0)
{
return APP_DRV_FIFO_RESULT_NOT_MEM;
}
// Check if application has requested only the size.
if(data == NULL)
{
return APP_DRV_FIFO_RESULT_SUCCESS;
}
for(index = 0; index < write_size; index++)
{
//push
fifo->data[fifo->end & fifo->size_mask] = data[index];
fifo->end++;
}
(*p_write_length) = write_size;
return APP_DRV_FIFO_RESULT_SUCCESS;
}
app_drv_fifo_result_t
app_drv_fifo_write_from_same_addr(app_drv_fifo_t *fifo, uint8_t *data, uint16_t write_length)
{
if(fifo == NULL)
{
return APP_DRV_FIFO_RESULT_NULL;
}
const uint16_t available_count = fifo->size_mask - fifo_length(fifo) + 1;
const uint16_t requested_len = (write_length);
uint16_t index = 0;
uint16_t write_size = MIN(requested_len, available_count);
// Check if the FIFO is FULL.
if(available_count == 0)
{
return APP_DRV_FIFO_RESULT_NOT_MEM;
}
for(index = 0; index < write_size; index++)
{
//push
fifo->data[fifo->end & fifo->size_mask] = data[0];
fifo->end++;
}
return APP_DRV_FIFO_RESULT_SUCCESS;
}
app_drv_fifo_result_t
app_drv_fifo_read(app_drv_fifo_t *fifo, uint8_t *data, uint16_t *p_read_length)
{
if(fifo == NULL)
{
return APP_DRV_FIFO_RESULT_NULL;
}
if(p_read_length == NULL)
{
return APP_DRV_FIFO_RESULT_NULL;
}
const uint16_t byte_count = fifo_length(fifo);
const uint16_t requested_len = (*p_read_length);
uint32_t index = 0;
uint32_t read_size = MIN(requested_len, byte_count);
if(byte_count == 0)
{
return APP_DRV_FIFO_RESULT_NOT_FOUND;
}
//PRINT("read size = %d,byte_count = %d\r\n",read_size,byte_count);
for(index = 0; index < read_size; index++)
{
//pop
data[index] = fifo->data[fifo->begin & fifo->size_mask];
fifo->begin++;
}
(*p_read_length) = read_size;
return APP_DRV_FIFO_RESULT_SUCCESS;
}
app_drv_fifo_result_t
app_drv_fifo_read_to_same_addr(app_drv_fifo_t *fifo, uint8_t *data, uint16_t read_length)
{
if(fifo == NULL)
{
return APP_DRV_FIFO_RESULT_NULL;
}
const uint16_t byte_count = fifo_length(fifo);
const uint16_t requested_len = (read_length);
uint32_t index = 0;
uint32_t read_size = MIN(requested_len, byte_count);
for(index = 0; index < read_size; index++)
{
//pop
data[0] = fifo->data[fifo->begin & fifo->size_mask];
fifo->begin++;
}
return APP_DRV_FIFO_RESULT_SUCCESS;
}

View File

@ -0,0 +1,240 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : peripheral.C
* Author : WCH
* Version : v1.0
* Date : 2020/11/26
* 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.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "../inc/config.h"
#include "../Profile/devinfoservice.h"
#include "../Profile/gattprofile.h"
#include "../inc/peripheral.h"
#include "../inc/app_uart.h"
#include "xs_base.h"
/*********************************************************************
* MACROS
*/
//The buffer length should be a power of 2
#define APP_UART_TX_BUFFER_LENGTH 512U
#define APP_UART_RX_BUFFER_LENGTH 2048U
/*********************************************************************
* CONSTANTS
*/
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
uint8_t to_test_buffer[BLE_BUFF_MAX_LEN - 4 - 3];
app_drv_fifo_t app_uart_tx_fifo;
app_drv_fifo_t app_uart_rx_fifo;
//interupt uart rx flag ,clear at main loop
bool uart_rx_flag = false;
//for interrupt rx blcak hole ,when uart rx fifo full
uint8_t for_uart_rx_black_hole = 0;
//fifo length less that MTU-3, retry times
uint32_t uart_to_ble_send_evt_cnt = 0;
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
//
//The tx buffer and rx buffer for app_drv_fifo
//length should be a power of 2
static uint8_t app_uart_tx_buffer[APP_UART_TX_BUFFER_LENGTH] = {0};
static uint8_t app_uart_rx_buffer[APP_UART_RX_BUFFER_LENGTH] = {0};
/*********************************************************************
* LOCAL FUNCTIONS
*/
/*********************************************************************
* PROFILE CALLBACKS
*/
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn app_uart_process
*
* @brief process uart data
*
* @return NULL
*/
void app_uart_process(void)
{
uint8_t data;
__disable_irq();
if(uart_rx_flag)
{
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
uart_rx_flag = false;
}
__enable_irq();
while(app_drv_fifo_length(&app_uart_tx_fifo))
{
app_drv_fifo_read_to_same_addr(&app_uart_tx_fifo, (uint8_t *)&data, 1);
// USART_SendData(USART, data);
KPrintf("%c", data);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) /* waiting for sending finish */
{
}
}
}
/*********************************************************************
* @fn app_uart_init
*
* @brief init uart
*
* @return NULL
*/
void app_uart_init()
{
//tx fifo and tx fifo
//The buffer length should be a power of 2
app_drv_fifo_init(&app_uart_tx_fifo, app_uart_tx_buffer, APP_UART_TX_BUFFER_LENGTH);
app_drv_fifo_init(&app_uart_rx_fifo, app_uart_rx_buffer, APP_UART_RX_BUFFER_LENGTH);
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
//uart3 init
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* USART3 TX-->B.10 RX-->B.11 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &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(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART3, ENABLE);
}
/*********************************************************************
* @fn app_uart_tx_data
*
* @brief app_uart_tx_data
*
* @return NULL
*/
void app_uart_tx_data(uint8_t *data, uint16_t length)
{
uint16_t write_length = length;
app_drv_fifo_write(&app_uart_tx_fifo, data, &write_length);
}
/*********************************************************************
* @fn UART3_IRQHandler
*
* @brief Not every uart reception will end with a UART_II_RECV_TOUT
* UART_II_RECV_TOUT can only be triggered when R8_UARTx_RFC is not 0
* Here we cannot rely UART_II_RECV_TOUT as the end of a uart reception
*
* @return NULL
*/
__attribute__((interrupt()))
void USART3_IRQHandler(void)
{
uint16_t error;
uint8_t data;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
data = USART_ReceiveData(USART3);
error = app_drv_fifo_write_from_same_addr(&app_uart_rx_fifo, (uint8_t *)&data, 1);
if(error != APP_DRV_FIFO_RESULT_SUCCESS)
{
KPrintf("APP_DRV_FIFO_RESULT_NOT_MEM\r\n");
}
uart_rx_flag = true;
}
}
/*********************************************************************
* @fn on_bleuartServiceEvTMOS_SystemProcesst
*
* @brief ble uart service callback handler
*
* @return NULL
*/
void on_bleuartServiceEvt(uint16_t connection_handle, ble_uart_evt_t *p_evt)
{
switch(p_evt->type)
{
case BLE_UART_EVT_TX_NOTI_DISABLED:
KPrintf("%02x:bleuart_EVT_TX_NOTI_DISABLED\r\n", connection_handle);
break;
case BLE_UART_EVT_TX_NOTI_ENABLED:
KPrintf("%02x:bleuart_EVT_TX_NOTI_ENABLED\r\n", connection_handle);
break;
case BLE_UART_EVT_BLE_DATA_RECIEVED:
KPrintf("BLE RX DATA len:%d\r\n", p_evt->data.length);
//for notify back test
//to ble
uint16_t to_write_length = p_evt->data.length;
app_drv_fifo_write(&app_uart_rx_fifo, (uint8_t *)p_evt->data.p_data, &to_write_length);
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
//end of nofify back test
//ble to uart
app_uart_tx_data((uint8_t *)p_evt->data.p_data, p_evt->data.length);
break;
default:
break;
}
}
/*********************************************************************
*********************************************************************/

View File

@ -0,0 +1,379 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : ble_uart_service.c
* Author : WCH
* Version : V1.1
* Date : 2022/01/19
* 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.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "../inc/config.h"
#include "../Profile/gattprofile.h"
#include "stdint.h"
#include "../inc/ble_uart_service.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
#define SERVAPP_NUM_ATTR_SUPPORTED 7
#define RAWPASS_TX_VALUE_HANDLE 4
#define RAWPASS_RX_VALUE_HANDLE 2
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
////ble_uart GATT Profile Service UUID
//const uint8_t ble_uart_ServiceUUID[ATT_UUID_SIZE] =
//{0x55, 0xe4,0x05,0xd2,0xaf,0x9f,0xa9,0x8f,0xe5,0x4a,0x7d,0xfe,0x43,0x53,0x53,0x49};
//// Characteristic rx uuid
//const uint8_t ble_uart_RxCharUUID[ATT_UUID_SIZE] =
//{0xb3,0x9b,0x72,0x34,0xbe,0xec, 0xd4,0xa8,0xf4,0x43,0x41,0x88,0x43,0x53,0x53,0x49};
//// Characteristic tx uuid
//const uint8_t ble_uart_TxCharUUID[ATT_UUID_SIZE] =
//{0x16,0x96,0x24,0x47,0xc6,0x23, 0x61,0xba,0xd9,0x4b,0x4d,0x1e,0x43,0x53,0x53,0x49};
// ble_uart GATT Profile Service UUID
const uint8_t ble_uart_ServiceUUID[ATT_UUID_SIZE] =
{0x9F, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E};
// Characteristic rx uuid
const uint8_t ble_uart_RxCharUUID[ATT_UUID_SIZE] =
{0x9F, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x02, 0x00, 0x40, 0x6E};
// Characteristic tx uuid
const uint8_t ble_uart_TxCharUUID[ATT_UUID_SIZE] =
{0x9F, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E};
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
static ble_uart_ProfileChangeCB_t ble_uart_AppCBs = NULL;
/*********************************************************************
* Profile Attributes - variables
*/
// Profile Service attribute
static const gattAttrType_t ble_uart_Service = {ATT_UUID_SIZE, ble_uart_ServiceUUID};
// Profile Characteristic 1 Properties
//static uint8_t ble_uart_RxCharProps = GATT_PROP_WRITE_NO_RSP| GATT_PROP_WRITE;
static uint8_t ble_uart_RxCharProps = GATT_PROP_WRITE_NO_RSP;
// Characteristic 1 Value
static uint8_t ble_uart_RxCharValue[BLE_UART_RX_BUFF_SIZE];
//static uint8_t ble_uart_RxCharValue[1];
// Profile Characteristic 2 Properties
//static uint8_t ble_uart_TxCharProps = GATT_PROP_NOTIFY| GATT_PROP_INDICATE;
static uint8_t ble_uart_TxCharProps = GATT_PROP_NOTIFY;
// Characteristic 2 Value
static uint8_t ble_uart_TxCharValue = 0;
// Simple Profile Characteristic 2 User Description
static gattCharCfg_t ble_uart_TxCCCD[4];
/*********************************************************************
* Profile Attributes - Table
*/
static gattAttribute_t ble_uart_ProfileAttrTbl[] = {
// Simple Profile Service
{
{ATT_BT_UUID_SIZE, primaryServiceUUID}, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8_t *)&ble_uart_Service /* pValue */
},
// Characteristic 1 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&ble_uart_RxCharProps},
// Characteristic Value 1
{
{ATT_UUID_SIZE, ble_uart_RxCharUUID},
GATT_PERMIT_WRITE,
0,
&ble_uart_RxCharValue[0]},
// Characteristic 2 Declaration
{
{ATT_BT_UUID_SIZE, characterUUID},
GATT_PERMIT_READ,
0,
&ble_uart_TxCharProps},
// Characteristic Value 2
{
{ATT_UUID_SIZE, ble_uart_TxCharUUID},
0,
0,
(uint8_t *)&ble_uart_TxCharValue},
// Characteristic 2 User Description
{
{ATT_BT_UUID_SIZE, clientCharCfgUUID},
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8_t *)ble_uart_TxCCCD},
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static bStatus_t ble_uart_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method);
static bStatus_t ble_uart_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method);
static void ble_uart_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType);
/*********************************************************************
* PROFILE CALLBACKS
*/
// Simple Profile Service Callbacks
gattServiceCBs_t ble_uart_ProfileCBs = {
ble_uart_ReadAttrCB, // Read callback function pointer
ble_uart_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn ble_uart_AddService
*
* @brief Initializes the Simple Profile service by registering
* GATT attributes with the GATT server.
*
* @param services - services to add. This is a bit map and can
* contain more than one service.
*
* @return Success or Failure
*/
bStatus_t ble_uart_add_service(ble_uart_ProfileChangeCB_t cb)
{
uint8_t status = SUCCESS;
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, ble_uart_TxCCCD);
// Register with Link DB to receive link status change callback
linkDB_Register(ble_uart_HandleConnStatusCB);
// ble_uart_TxCCCD.connHandle = INVALID_CONNHANDLE;
// ble_uart_TxCCCD.value = 0;
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService(ble_uart_ProfileAttrTbl,
GATT_NUM_ATTRS(ble_uart_ProfileAttrTbl),
GATT_MAX_ENCRYPT_KEY_SIZE,
&ble_uart_ProfileCBs);
if(status != SUCCESS)
PRINT("Add ble uart service failed!\n");
ble_uart_AppCBs = cb;
return (status);
}
/*********************************************************************
* @fn ble_uart_ReadAttrCB
*
* @brief Read an attribute.
*
* @param connHandle - connection message was received on
* @param pAttr - pointer to attribute
* @param pValue - pointer to data to be read
* @param pLen - length of data to be read
* @param offset - offset of the first octet to be read
* @param maxLen - maximum length of data to be read
*
* @return Success or Failure
*/
static bStatus_t ble_uart_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
{
bStatus_t status = SUCCESS;
PRINT("ReadAttrCB\n");
// Make sure it's not a blob operation (no attributes in the profile are long)
if(pAttr->type.len == ATT_BT_UUID_SIZE)
{
// 16-bit UUID
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
if(uuid == GATT_CLIENT_CHAR_CFG_UUID)
{
*pLen = 2;
tmos_memcpy(pValue, pAttr->pValue, 2);
}
}
else
{
if(tmos_memcmp(pAttr->type.uuid, ble_uart_TxCharUUID, 16))
{
*pLen = 1;
pValue[0] = '1';
}
else if(tmos_memcmp(pAttr->type.uuid, ble_uart_RxCharUUID, 16))
{
PRINT("read tx char\n");
}
}
return (status);
}
/*********************************************************************
* @fn simpleProfile_WriteAttrCB
*
* @brief Validate attribute data prior to a write operation
*
* @param connHandle - connection message was received on
* @param pAttr - pointer to attribute
* @param pValue - pointer to data to be written
* @param len - length of data
* @param offset - offset of the first octet to be written
*
* @return Success or Failure
*/
static bStatus_t ble_uart_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
{
bStatus_t status = SUCCESS;
//uint8_t notifyApp = 0xFF;
// If attribute permissions require authorization to write, return error
if(gattPermitAuthorWrite(pAttr->permissions))
{
// Insufficient authorization
return (ATT_ERR_INSUFFICIENT_AUTHOR);
}
if(pAttr->type.len == ATT_BT_UUID_SIZE)
{
// 16-bit UUID
uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
if(uuid == GATT_CLIENT_CHAR_CFG_UUID)
{
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len,
offset, GATT_CLIENT_CFG_NOTIFY);
if(status == SUCCESS && ble_uart_AppCBs)
{
uint16_t charCfg = BUILD_UINT16(pValue[0], pValue[1]);
ble_uart_evt_t evt;
//PRINT("CCCD set: [%d]\n", charCfg);
evt.type = (charCfg == GATT_CFG_NO_OPERATION) ? BLE_UART_EVT_TX_NOTI_DISABLED : BLE_UART_EVT_TX_NOTI_ENABLED;
ble_uart_AppCBs(connHandle, &evt);
}
}
}
else
{
// 128-bit UUID
if(pAttr->handle == ble_uart_ProfileAttrTbl[RAWPASS_RX_VALUE_HANDLE].handle)
{
if(ble_uart_AppCBs)
{
ble_uart_evt_t evt;
evt.type = BLE_UART_EVT_BLE_DATA_RECIEVED;
evt.data.length = (uint16_t)len;
evt.data.p_data = pValue;
ble_uart_AppCBs(connHandle, &evt);
}
}
}
return (status);
}
/*********************************************************************
* @fn simpleProfile_HandleConnStatusCB
*
* @brief Simple Profile link status change handler function.
*
* @param connHandle - connection handle
* @param changeType - type of change
*
* @return none
*/
static void ble_uart_HandleConnStatusCB(uint16_t connHandle, uint8_t changeType)
{
// Make sure this is not loopback connection
if(connHandle != LOOPBACK_CONNHANDLE)
{
// Reset Client Char Config if connection has dropped
if((changeType == LINKDB_STATUS_UPDATE_REMOVED) ||
((changeType == LINKDB_STATUS_UPDATE_STATEFLAGS) &&
(!linkDB_Up(connHandle))))
{
//ble_uart_TxCCCD[0].value = 0;
GATTServApp_InitCharCfg(connHandle, ble_uart_TxCCCD);
//PRINT("clear client configuration\n");
}
}
}
uint8_t ble_uart_notify_is_ready(uint16_t connHandle)
{
return (GATT_CLIENT_CFG_NOTIFY == GATTServApp_ReadCharCfg(connHandle, ble_uart_TxCCCD));
}
/*********************************************************************
* @fn BloodPressure_IMeasNotify
*
* @brief Send a notification containing a bloodPressure
* measurement.
*
* @param connHandle - connection handle
* @param pNoti - pointer to notification structure
*
* @return Success or Failure
*/
bStatus_t ble_uart_notify(uint16_t connHandle, attHandleValueNoti_t *pNoti, uint8_t taskId)
{
//uint16_t value = ble_uart_TxCCCD[0].value;
uint16_t value = GATTServApp_ReadCharCfg(connHandle, ble_uart_TxCCCD);
// If notifications enabled
if(value & GATT_CLIENT_CFG_NOTIFY)
{
// Set the handle
pNoti->handle = ble_uart_ProfileAttrTbl[RAWPASS_TX_VALUE_HANDLE].handle;
// Send the Indication
return GATT_Notification(connHandle, pNoti, FALSE);
}
return bleIncorrectMode;
}
/*********************************************************************
*********************************************************************/

View File

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

View File

@ -0,0 +1,651 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : peripheral.C
* Author : WCH
* Version : v1.0
* Date : 2020/11/26
* 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.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "../inc/config.h"
#include "../Profile/devinfoservice.h"
#include "../Profile/gattprofile.h"
#include "../inc/peripheral.h"
#include "../inc/ble_uart_service.h"
#include "../inc/app_drv_fifo.h"
#include "../inc/app_uart.h"
#include "xs_base.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
// How often to perform periodic event
#define SBP_PERIODIC_EVT_PERIOD 1600
// How often to perform read rssi event
#define SBP_READ_RSSI_EVT_PERIOD 3200
// Parameter update delay
#define SBP_PARAM_UPDATE_DELAY 6400
// What is the advertising interval when device is discoverable (units of 625us, 80=50ms)
#define DEFAULT_ADVERTISING_INTERVAL 160
// Limited discoverable mode advertises for 30.72s, and then stops
// General discoverable mode advertises indefinitely
#define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL
// Minimum connection interval (units of 1.25ms, 10=12.5ms)
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 8
// Maximum connection interval (units of 1.25ms, 100=125ms)
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 20
// Slave latency to use parameter update
#define DEFAULT_DESIRED_SLAVE_LATENCY 0
// Supervision timeout value (units of 10ms, 100=1s)
#define DEFAULT_DESIRED_CONN_TIMEOUT 100
// Company Identifier: WCH
#define WCH_COMPANY_ID 0x07D7
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
uint8_t Peripheral_TaskID = INVALID_TASK_ID; // Task ID for internal task/event processing
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
//for send to ble
typedef enum
{
SEND_TO_BLE_TO_SEND = 1,
SEND_TO_BLE_ALLOC_FAILED,
SEND_TO_BLE_SEND_FAILED,
} send_to_ble_state_t;
send_to_ble_state_t send_to_ble_state = SEND_TO_BLE_TO_SEND;
blePaControlConfig_t pa_lna_ctl;
//static uint8_t Peripheral_TaskID = INVALID_TASK_ID; // Task ID for internal task/event processing
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8_t scanRspData[] = {
// complete name
13, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'w', 'c', 'h', '_', 'b', 'l', 'e', '_', 'u', 'a', 'r', 't',
// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL), // 100ms
HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL), // 1s
HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};
// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8_t advertData[] = {
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
LO_UINT16(SIMPLEPROFILE_SERV_UUID),
HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
// GAP GATT Attributes
static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "ch32v208_ble_uart";
// Connection item list
static peripheralConnItem_t peripheralConnList;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void Peripheral_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
static void peripheralStateNotificationCB(gapRole_States_t newState, gapRoleEvent_t *pEvent);
static void peripheralParamUpdateCB(uint16_t connHandle, uint16_t connInterval,
uint16_t connSlaveLatency, uint16_t connTimeout);
static void peripheralInitConnItem(peripheralConnItem_t *peripheralConnList);
static void peripheralRssiCB(uint16_t connHandle, int8_t rssi);
/*********************************************************************
* PROFILE CALLBACKS
*/
// GAP Role Callbacks
static gapRolesCBs_t Peripheral_PeripheralCBs = {
peripheralStateNotificationCB, // Profile State Change Callbacks
peripheralRssiCB, // When a valid RSSI is read from controller (not used by application)
peripheralParamUpdateCB};
// Broadcast Callbacks
static gapRolesBroadcasterCBs_t Broadcaster_BroadcasterCBs = {
NULL, // Not used in peripheral role
NULL // Receive scan request callback
};
// GAP Bond Manager Callbacks
static gapBondCBs_t Peripheral_BondMgrCBs = {
NULL, // Passcode callback (not used by application)
NULL // Pairing / Bonding state Callback (not used by application)
};
extern uint8_t disconnectFlag;
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn Peripheral_Init
*
* @brief Initialization function for the Peripheral App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by TMOS. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void Peripheral_Init()
{
Peripheral_TaskID = TMOS_ProcessEventRegister(Peripheral_ProcessEvent);
// Setup the GAP Peripheral Role Profile
{
uint8_t initial_advertising_enable = TRUE;
uint16_t desired_min_interval = 6;
uint16_t desired_max_interval = 1000;
// Set the GAP Role Parameters
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desired_min_interval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desired_max_interval);
}
// Set advertising interval
{
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
}
// Setup the GAP Bond Manager
{
uint32_t passkey = 0; // passkey "000000"
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
uint8_t mitm = TRUE;
uint8_t bonding = TRUE;
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}
// Initialize GATT attributes
GGS_AddService(GATT_ALL_SERVICES); // GAP
GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
DevInfo_AddService(); // Device Information Service
ble_uart_add_service(on_bleuartServiceEvt);
// Set the GAP Characteristics
GGS_SetParameter(GGS_DEVICE_NAME_ATT, sizeof(attDeviceName), attDeviceName);
// Init Connection Item
peripheralInitConnItem(&peripheralConnList);
// Register receive scan request callback
GAPRole_BroadcasterSetCB(&Broadcaster_BroadcasterCBs);
// Setup a delayed profile startup
tmos_set_event(Peripheral_TaskID, SBP_START_DEVICE_EVT);
}
/*********************************************************************
* @fn peripheralInitConnItem
*
* @brief Init Connection Item
*
* @param peripheralConnList -
*
* @return NULL
*/
static void peripheralInitConnItem(peripheralConnItem_t *peripheralConnList)
{
peripheralConnList->connHandle = GAP_CONNHANDLE_INIT;
peripheralConnList->connInterval = 0;
peripheralConnList->connSlaveLatency = 0;
peripheralConnList->connTimeout = 0;
}
uint32_t get_fattime(void)
{
return 0;
}
/*********************************************************************
* @fn Peripheral_ProcessEvent
*
* @brief Peripheral Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @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
*/
uint16_t Peripheral_ProcessEvent(uint8_t task_id, uint16_t events)
{
static attHandleValueNoti_t noti;
// VOID task_id; // TMOS required parameter that isn't used in this function
if(events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if((pMsg = tmos_msg_receive(Peripheral_TaskID)) != NULL)
{
Peripheral_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if(events & SBP_START_DEVICE_EVT)
{
// Start the Device
GAPRole_PeripheralStartDevice(Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs);
return (events ^ SBP_START_DEVICE_EVT);
}
if(events & SBP_PARAM_UPDATE_EVT)
{
// Send connect param update request
GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle,
DEFAULT_DESIRED_MIN_CONN_INTERVAL,
DEFAULT_DESIRED_MAX_CONN_INTERVAL,
DEFAULT_DESIRED_SLAVE_LATENCY,
DEFAULT_DESIRED_CONN_TIMEOUT,
Peripheral_TaskID);
// GAPRole_PeripheralConnParamUpdateReq( peripheralConnList.connHandle,
// 10,
// 20,
// 0,
// 400,
// Peripheral_TaskID);
return (events ^ SBP_PARAM_UPDATE_EVT);
}
if(events & UART_TO_BLE_SEND_EVT)
{
static uint16_t read_length = 0;
;
uint8_t result = 0xff;
switch(send_to_ble_state)
{
case SEND_TO_BLE_TO_SEND:
//notify is not enabled
if(!ble_uart_notify_is_ready(peripheralConnList.connHandle))
{
if(peripheralConnList.connHandle == GAP_CONNHANDLE_INIT)
{
//connection lost, flush rx fifo here
app_drv_fifo_flush(&app_uart_rx_fifo);
}
break;
}
read_length = ATT_GetMTU(peripheralConnList.connHandle) - 3;
if(app_drv_fifo_length(&app_uart_rx_fifo) >= read_length)
{
KPrintf("FIFO_LEN:%d\r\n", app_drv_fifo_length(&app_uart_rx_fifo));
result = app_drv_fifo_read(&app_uart_rx_fifo, to_test_buffer, &read_length);
uart_to_ble_send_evt_cnt = 0;
}
else
{
if(uart_to_ble_send_evt_cnt > 10)
{
result = app_drv_fifo_read(&app_uart_rx_fifo, to_test_buffer, &read_length);
uart_to_ble_send_evt_cnt = 0;
}
else
{
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 4);
uart_to_ble_send_evt_cnt++;
// KPrintf("NO TIME OUT\r\n");
}
}
if(APP_DRV_FIFO_RESULT_SUCCESS == result)
{
noti.len = read_length;
noti.pValue = GATT_bm_alloc(peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0);
if(noti.pValue != NULL)
{
tmos_memcpy(noti.pValue, to_test_buffer, noti.len);
result = ble_uart_notify(peripheralConnList.connHandle, &noti, 0);
if(result != SUCCESS)
{
KPrintf("R1:%02x\r\n", result);
send_to_ble_state = SEND_TO_BLE_SEND_FAILED;
GATT_bm_free((gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI);
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
}
else
{
send_to_ble_state = SEND_TO_BLE_TO_SEND;
//app_fifo_write(&app_uart_tx_fifo,to_test_buffer,&read_length);
//app_drv_fifo_write(&app_uart_tx_fifo,to_test_buffer,&read_length);
read_length = 0;
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
}
}
else
{
send_to_ble_state = SEND_TO_BLE_ALLOC_FAILED;
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
}
}
else
{
//send_to_ble_state = SEND_TO_BLE_FIFO_EMPTY;
}
break;
case SEND_TO_BLE_ALLOC_FAILED:
case SEND_TO_BLE_SEND_FAILED:
noti.len = read_length;
noti.pValue = GATT_bm_alloc(peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0);
if(noti.pValue != NULL)
{
tmos_memcpy(noti.pValue, to_test_buffer, noti.len);
result = ble_uart_notify(peripheralConnList.connHandle, &noti, 0);
if(result != SUCCESS)
{
KPrintf("R2:%02x\r\n", result);
send_to_ble_state = SEND_TO_BLE_SEND_FAILED;
GATT_bm_free((gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI);
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
}
else
{
send_to_ble_state = SEND_TO_BLE_TO_SEND;
//app_drv_fifo_write(&app_uart_tx_fifo,to_test_buffer,&read_length);
read_length = 0;
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
}
}
else
{
send_to_ble_state = SEND_TO_BLE_ALLOC_FAILED;
tmos_start_task(Peripheral_TaskID, UART_TO_BLE_SEND_EVT, 2);
}
break;
default:
break;
}
return (events ^ UART_TO_BLE_SEND_EVT);
}
// Discard unknown events
return 0;
}
/*********************************************************************
* @fn Peripheral_ProcessTMOSMsg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void Peripheral_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
{
switch(pMsg->event)
{
default:
break;
}
}
/*********************************************************************
* @fn Peripheral_LinkEstablished
*
* @brief Process link established.
*
* @param pEvent - event to process
*
* @return none
*/
static void Peripheral_LinkEstablished(gapRoleEvent_t *pEvent)
{
gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *)pEvent;
// See if already connected
if(peripheralConnList.connHandle != GAP_CONNHANDLE_INIT)
{
GAPRole_TerminateLink(pEvent->linkCmpl.connectionHandle);
KPrintf("Connection max...\n");
}
else
{
peripheralConnList.connHandle = event->connectionHandle;
peripheralConnList.connInterval = event->connInterval;
peripheralConnList.connSlaveLatency = event->connLatency;
peripheralConnList.connTimeout = event->connTimeout;
// Set timer for param update event
tmos_start_task(Peripheral_TaskID, SBP_PARAM_UPDATE_EVT, SBP_PARAM_UPDATE_DELAY);
KPrintf("Conn %x - Int %x \n", event->connectionHandle, event->connInterval);
}
}
/*********************************************************************
* @fn Peripheral_LinkTerminated
*
* @brief Process link terminated.
*
* @param pEvent - event to process
*
* @return none
*/
static void Peripheral_LinkTerminated(gapRoleEvent_t *pEvent)
{
gapTerminateLinkEvent_t *event = (gapTerminateLinkEvent_t *)pEvent;
if(event->connectionHandle == peripheralConnList.connHandle)
{
peripheralConnList.connHandle = GAP_CONNHANDLE_INIT;
peripheralConnList.connInterval = 0;
peripheralConnList.connSlaveLatency = 0;
peripheralConnList.connTimeout = 0;
// Restart advertising
{
uint8_t advertising_enable = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertising_enable);
}
}
else
{
KPrintf("ERR..\n");
}
}
/*********************************************************************
* @fn peripheralRssiCB
*
* @brief RSSI callback.
*
* @param connHandle - connection handle
* @param rssi - RSSI
*
* @return none
*/
static void peripheralRssiCB(uint16_t connHandle, int8_t rssi)
{
KPrintf("RSSI -%d dB Conn %x \n", -rssi, connHandle);
}
/*********************************************************************
* @fn peripheralParamUpdateCB
*
* @brief Parameter update complete callback
*
* @param connHandle - connect handle
* connInterval - connect interval
* connSlaveLatency - connect slave latency
* connTimeout - connect timeout
*
* @return none
*/
static void peripheralParamUpdateCB(uint16_t connHandle, uint16_t connInterval,
uint16_t connSlaveLatency, uint16_t connTimeout)
{
if(connHandle == peripheralConnList.connHandle)
{
peripheralConnList.connInterval = connInterval;
peripheralConnList.connSlaveLatency = connSlaveLatency;
peripheralConnList.connTimeout = connTimeout;
KPrintf("Update %x - Int %x \n", connHandle, connInterval);
}
else
{
KPrintf("peripheralParamUpdateCB err..\n");
}
}
/*********************************************************************
* @fn peripheralStateNotificationCB
*
* @brief Notification from the profile of a state change.
*
* @param newState - new state
*
* @return none
*/
static void peripheralStateNotificationCB(gapRole_States_t newState, gapRoleEvent_t *pEvent)
{
switch(newState & GAPROLE_STATE_ADV_MASK)
{
case GAPROLE_STARTED:
KPrintf("Initialized..\n");
break;
case GAPROLE_ADVERTISING:
if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
{
Peripheral_LinkTerminated(pEvent);
}
KPrintf("Advertising..\n");
break;
case GAPROLE_CONNECTED:
if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
{
Peripheral_LinkEstablished(pEvent);
KPrintf("Connected..\n");
}
break;
case GAPROLE_CONNECTED_ADV:
KPrintf("Connected Advertising..\n");
break;
case GAPROLE_WAITING:
if(pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT)
{
KPrintf("Waiting for advertising..\n");
}
else if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
{
Peripheral_LinkTerminated(pEvent);
disconnectFlag = 1;
KPrintf("Disconnected.. Reason:%x\n", pEvent->linkTerminate.reason);
}
else if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
{
if(pEvent->gap.hdr.status != SUCCESS)
{
KPrintf("Waiting for advertising..\n");
}
else
{
KPrintf("Error..\n");
}
}
else
{
KPrintf("Error..%x\n", pEvent->gap.opcode);
}
break;
case GAPROLE_ERROR:
KPrintf("Error..\n");
break;
default:
break;
}
}
/*********************************************************************
*********************************************************************/

View File

@ -0,0 +1,73 @@
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.1
* Date : 2020/08/06
* Description : Peripheral slave application main function and task system initialization
*********************************************************************************
* 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 "../inc/config.h"
#include "../inc/HAL.h"
#include "../Profile/gattprofile.h"
#include "../inc/peripheral.h"
#include "../inc/app_uart.h"
#include "shell.h"
#include "xs_base.h"
#include "debug.h"
/*********************************************************************
* GLOBAL TYPEDEFS
*/
__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE / 4];
#if(defined(BLE_MAC)) && (BLE_MAC == TRUE)
uint8_t const MacAddr[6] = {0x84, 0xC2, 0xE4, 0x03, 0x02, 0x02};
#endif
uint8_t disconnectFlag = 1; // ble disconnect flag
/*********************************************************************
* @fn Main_Circulation
*
* @brief Main loop
*
* @return none
*/
__attribute__((section(".highcode")))
__attribute__((noinline))
void Main_Circulation(void)
{
while(1)
{
if (disconnectFlag) {
break;
}
TMOS_SystemProcess();
app_uart_process();
}
}
/*******************************************************************************
* Function Name : main
* Description : Main function
* Input : None
* Output : None
* Return : None
*******************************************************************************/
int test_ble(int argc, char *argv[])
{
KPrintf("%s\n", VER_LIB);
GAPRole_PeripheralInit();
Peripheral_Init();
KPrintf("BLE Peripheral Slave Init Success.\n");
app_uart_init();
disconnectFlag = 0; // reset disconnect flag
Main_Circulation();
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
test_ble, test_ble, test test_ble command);

View File

@ -400,6 +400,7 @@ int ping(int argc, char *argv[]) {
}
WCHNET_SocketClose(SocketId, TCP_CLOSE_NORMAL);
ICMPCnt = 0; // restore the original ICMPCnt
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ OBJS := $(shell cat make.obj)
$(TARGET): $(OBJS)
@echo ------------------------------------------------
@echo link $(TARGET)
@$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_LWIP) $(LINK_MUSLLIB) $(LINK_MONGOOSE) $(LINK_WCH_NET) $(LIBCC)
@$(CROSS_COMPILE)g++ -o $@ $($(LINK_FLAGS)) $(OBJS) $(LINK_LWIP) $(LINK_MUSLLIB) $(LINK_MONGOOSE) $(LINK_WCH_NET) $(LIBCC) $(LINK_WCH_BLE)
@echo ------------------------------------------------
@$(CROSS_COMPILE)objcopy -O binary $@ XiZi-$(BOARD)$(COMPILE_TYPE).bin
@$(CROSS_COMPILE)objdump -S $@ > XiZi-$(BOARD)$(COMPILE_TYPE).asm