zhaohe 1 year ago
parent
commit
ae9a76be52
  1. 11
      .gitignore
  2. 13
      README.md
  3. 379
      RTE/Device/nRF52833_xxAA/arm_startup_nrf52833.s
  4. 329
      RTE/Device/nRF52833_xxAA/system_nrf52.c
  5. 14
      ble_app_uart_c.eww
  6. 3637
      ble_app_uart_c_pca10100_s122.uvguix.h_zha
  7. 1132
      ble_app_uart_c_pca10100_s122.uvoptx
  8. 7155
      ble_app_uart_c_pca10100_s122.uvprojx
  9. 12041
      config/sdk_config.h
  10. 708
      main.c
  11. 302
      zble_nus_c.c
  12. 264
      zble_nus_c.h

11
.gitignore

@ -0,0 +1,11 @@
_build
app.uvguix.*
JLinkLog.txt
JLinkSettings.ini
RTE_Components.h
EventRecorderStub.scvd
app/.vscode
.vscode/uv4.log.lock
.vscode/keil-assistant.log
bin2/bl_temp.hex
bin2/settings.hex

13
README.md

@ -1,2 +1,15 @@
# dynamic_electrocardiograph_ble_server # dynamic_electrocardiograph_ble_server
```
V1:
1.会自动搜索包含下面服务的设备然后进行连接
6e400001-b5a3-f393-e0a9-e50e24dcca9e
2.支持以下UUID服务
6e400001-b5a3-f393-e0a9-e50e24dcca9e
6e400002-b5a3-f393-e0a9-e50e24dcca9e
6e400003-b5a3-f393-e0a9-e50e24dcca9e
6e400004-b5a3-f393-e0a9-e50e24dcca9e
3.接收到的蓝牙数据包,会在结尾添加
0x5A 0xA5
4.如果2ms内没有收到新的串口数据,会将之前收到的数据当作一包数据,发给蓝牙从机
```

379
RTE/Device/nRF52833_xxAA/arm_startup_nrf52833.s

@ -0,0 +1,379 @@
; Copyright (c) 2009-2021 ARM Limited. All rights reserved.
;
; SPDX-License-Identifier: Apache-2.0
;
; Licensed under the Apache License, Version 2.0 (the License); you may
; not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an AS IS BASIS, WITHOUT
; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; NOTICE: This file has been modified by Nordic Semiconductor ASA.
IF :DEF: __STARTUP_CONFIG
#ifdef __STARTUP_CONFIG
#include "startup_config.h"
#ifndef __STARTUP_CONFIG_STACK_ALIGNEMENT
#define __STARTUP_CONFIG_STACK_ALIGNEMENT 3
#endif
#endif
ENDIF
IF :DEF: __STARTUP_CONFIG
Stack_Size EQU __STARTUP_CONFIG_STACK_SIZE
ELIF :DEF: __STACK_SIZE
Stack_Size EQU __STACK_SIZE
ELSE
Stack_Size EQU 8192
ENDIF
IF :DEF: __STARTUP_CONFIG
Stack_Align EQU __STARTUP_CONFIG_STACK_ALIGNEMENT
ELSE
Stack_Align EQU 3
ENDIF
AREA STACK, NOINIT, READWRITE, ALIGN=Stack_Align
Stack_Mem SPACE Stack_Size
__initial_sp
IF :DEF: __STARTUP_CONFIG
Heap_Size EQU __STARTUP_CONFIG_HEAP_SIZE
ELIF :DEF: __HEAP_SIZE
Heap_Size EQU __HEAP_SIZE
ELSE
Heap_Size EQU 8192
ENDIF
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler
DCD NMI_Handler
DCD HardFault_Handler
DCD MemoryManagement_Handler
DCD BusFault_Handler
DCD UsageFault_Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler
DCD DebugMon_Handler
DCD 0 ; Reserved
DCD PendSV_Handler
DCD SysTick_Handler
; External Interrupts
DCD POWER_CLOCK_IRQHandler
DCD RADIO_IRQHandler
DCD UARTE0_UART0_IRQHandler
DCD SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler
DCD SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler
DCD NFCT_IRQHandler
DCD GPIOTE_IRQHandler
DCD SAADC_IRQHandler
DCD TIMER0_IRQHandler
DCD TIMER1_IRQHandler
DCD TIMER2_IRQHandler
DCD RTC0_IRQHandler
DCD TEMP_IRQHandler
DCD RNG_IRQHandler
DCD ECB_IRQHandler
DCD CCM_AAR_IRQHandler
DCD WDT_IRQHandler
DCD RTC1_IRQHandler
DCD QDEC_IRQHandler
DCD COMP_LPCOMP_IRQHandler
DCD SWI0_EGU0_IRQHandler
DCD SWI1_EGU1_IRQHandler
DCD SWI2_EGU2_IRQHandler
DCD SWI3_EGU3_IRQHandler
DCD SWI4_EGU4_IRQHandler
DCD SWI5_EGU5_IRQHandler
DCD TIMER3_IRQHandler
DCD TIMER4_IRQHandler
DCD PWM0_IRQHandler
DCD PDM_IRQHandler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD MWU_IRQHandler
DCD PWM1_IRQHandler
DCD PWM2_IRQHandler
DCD SPIM2_SPIS2_SPI2_IRQHandler
DCD RTC2_IRQHandler
DCD I2S_IRQHandler
DCD FPU_IRQHandler
DCD USBD_IRQHandler
DCD UARTE1_IRQHandler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD PWM3_IRQHandler
DCD 0 ; Reserved
DCD SPIM3_IRQHandler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
; Reset Handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemoryManagement_Handler\
PROC
EXPORT MemoryManagement_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler PROC
EXPORT POWER_CLOCK_IRQHandler [WEAK]
EXPORT RADIO_IRQHandler [WEAK]
EXPORT UARTE0_UART0_IRQHandler [WEAK]
EXPORT SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler [WEAK]
EXPORT SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler [WEAK]
EXPORT NFCT_IRQHandler [WEAK]
EXPORT GPIOTE_IRQHandler [WEAK]
EXPORT SAADC_IRQHandler [WEAK]
EXPORT TIMER0_IRQHandler [WEAK]
EXPORT TIMER1_IRQHandler [WEAK]
EXPORT TIMER2_IRQHandler [WEAK]
EXPORT RTC0_IRQHandler [WEAK]
EXPORT TEMP_IRQHandler [WEAK]
EXPORT RNG_IRQHandler [WEAK]
EXPORT ECB_IRQHandler [WEAK]
EXPORT CCM_AAR_IRQHandler [WEAK]
EXPORT WDT_IRQHandler [WEAK]
EXPORT RTC1_IRQHandler [WEAK]
EXPORT QDEC_IRQHandler [WEAK]
EXPORT COMP_LPCOMP_IRQHandler [WEAK]
EXPORT SWI0_EGU0_IRQHandler [WEAK]
EXPORT SWI1_EGU1_IRQHandler [WEAK]
EXPORT SWI2_EGU2_IRQHandler [WEAK]
EXPORT SWI3_EGU3_IRQHandler [WEAK]
EXPORT SWI4_EGU4_IRQHandler [WEAK]
EXPORT SWI5_EGU5_IRQHandler [WEAK]
EXPORT TIMER3_IRQHandler [WEAK]
EXPORT TIMER4_IRQHandler [WEAK]
EXPORT PWM0_IRQHandler [WEAK]
EXPORT PDM_IRQHandler [WEAK]
EXPORT MWU_IRQHandler [WEAK]
EXPORT PWM1_IRQHandler [WEAK]
EXPORT PWM2_IRQHandler [WEAK]
EXPORT SPIM2_SPIS2_SPI2_IRQHandler [WEAK]
EXPORT RTC2_IRQHandler [WEAK]
EXPORT I2S_IRQHandler [WEAK]
EXPORT FPU_IRQHandler [WEAK]
EXPORT USBD_IRQHandler [WEAK]
EXPORT UARTE1_IRQHandler [WEAK]
EXPORT PWM3_IRQHandler [WEAK]
EXPORT SPIM3_IRQHandler [WEAK]
POWER_CLOCK_IRQHandler
RADIO_IRQHandler
UARTE0_UART0_IRQHandler
SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler
SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler
NFCT_IRQHandler
GPIOTE_IRQHandler
SAADC_IRQHandler
TIMER0_IRQHandler
TIMER1_IRQHandler
TIMER2_IRQHandler
RTC0_IRQHandler
TEMP_IRQHandler
RNG_IRQHandler
ECB_IRQHandler
CCM_AAR_IRQHandler
WDT_IRQHandler
RTC1_IRQHandler
QDEC_IRQHandler
COMP_LPCOMP_IRQHandler
SWI0_EGU0_IRQHandler
SWI1_EGU1_IRQHandler
SWI2_EGU2_IRQHandler
SWI3_EGU3_IRQHandler
SWI4_EGU4_IRQHandler
SWI5_EGU5_IRQHandler
TIMER3_IRQHandler
TIMER4_IRQHandler
PWM0_IRQHandler
PDM_IRQHandler
MWU_IRQHandler
PWM1_IRQHandler
PWM2_IRQHandler
SPIM2_SPIS2_SPI2_IRQHandler
RTC2_IRQHandler
I2S_IRQHandler
FPU_IRQHandler
USBD_IRQHandler
UARTE1_IRQHandler
PWM3_IRQHandler
SPIM3_IRQHandler
B .
ENDP
ALIGN
; User Initial Stack & Heap
IF :DEF:__MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap PROC
LDR R0, = Heap_Mem
LDR R1, = (Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ENDP
ALIGN
ENDIF
END

329
RTE/Device/nRF52833_xxAA/system_nrf52.c

@ -0,0 +1,329 @@
/*
Copyright (c) 2009-2021 ARM Limited. All rights reserved.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the License); you may
not use this file except in compliance with the License.
You may obtain a copy of the License at
www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an AS IS BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
NOTICE: This file has been modified by Nordic Semiconductor ASA.
*/
/* NOTE: Template files (including this one) are application specific and therefore expected to
be copied into the application project folder prior to its use! */
#include <stdint.h>
#include <stdbool.h>
#include "nrf.h"
#include "nrf_peripherals.h"
#include "nrf52_erratas.h"
#include "system_nrf52.h"
#include "system_nrf52_approtect.h"
#define __SYSTEM_CLOCK_64M (64000000UL)
#if defined ( __CC_ARM )
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M;
#elif defined ( __ICCARM__ )
__root uint32_t SystemCoreClock = __SYSTEM_CLOCK_64M;
#elif defined ( __GNUC__ )
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M;
#endif
/* Select correct reset pin */
/* Handle DEVELOP_IN-targets first as they take precedence over the later macros */
#if defined (DEVELOP_IN_NRF52805) \
|| defined (DEVELOP_IN_NRF52810) \
|| defined (DEVELOP_IN_NRF52811) \
|| defined (DEVELOP_IN_NRF52832)
#define RESET_PIN 21
#elif defined (DEVELOP_IN_NRF52820) \
|| defined (DEVELOP_IN_NRF52833) \
|| defined (DEVELOP_IN_NRF52840)
#define RESET_PIN 18
#elif defined (NRF52805_XXAA) \
|| defined (NRF52810_XXAA) \
|| defined (NRF52811_XXAA) \
|| defined (NRF52832_XXAA) \
|| defined (NRF52832_XXAB)
#define RESET_PIN 21
#elif defined (NRF52820_XXAA) \
|| defined (NRF52833_XXAA) \
|| defined (NRF52840_XXAA)
#define RESET_PIN 18
#else
#error "A supported device macro must be defined."
#endif
/* -- NVMC utility functions -- */
/* Waits until NVMC is done with the current pending action */
void nvmc_wait(void)
{
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
}
/* Configure the NVMC to "mode".
Mode must be an enumerator of field NVMC_CONFIG_WEN */
void nvmc_config(uint32_t mode)
{
NRF_NVMC->CONFIG = mode << NVMC_CONFIG_WEN_Pos;
nvmc_wait();
}
void SystemCoreClockUpdate(void)
{
SystemCoreClock = __SYSTEM_CLOCK_64M;
}
void SystemInit(void)
{
/* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product
Specification to see which one). */
#if defined (ENABLE_SWO) && defined(CLOCK_TRACECONFIG_TRACEMUX_Pos)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos;
NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
#endif
/* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
Specification to see which ones). */
#if defined (ENABLE_TRACE) && defined(CLOCK_TRACECONFIG_TRACEMUX_Pos)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos;
NRF_P0->PIN_CNF[14] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_P0->PIN_CNF[15] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_P0->PIN_CNF[16] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
NRF_P0->PIN_CNF[20] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
#endif
#if NRF52_ERRATA_12_ENABLE_WORKAROUND
/* Workaround for Errata 12 "COMP: Reference ladder not correctly calibrated" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_12()){
*(volatile uint32_t *)0x40013540 = (*(uint32_t *)0x10000324 & 0x00001F00) >> 8;
}
#endif
#if NRF52_ERRATA_16_ENABLE_WORKAROUND
/* Workaround for Errata 16 "System: RAM may be corrupt on wakeup from CPU IDLE" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_16()){
*(volatile uint32_t *)0x4007C074 = 3131961357ul;
}
#endif
#if NRF52_ERRATA_31_ENABLE_WORKAROUND
/* Workaround for Errata 31 "CLOCK: Calibration values are not correctly loaded from FICR at reset" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_31()){
*(volatile uint32_t *)0x4000053C = ((*(volatile uint32_t *)0x10000244) & 0x0000E000) >> 13;
}
#endif
#if NRF52_ERRATA_32_ENABLE_WORKAROUND
/* Workaround for Errata 32 "DIF: Debug session automatically enables TracePort pins" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_32()){
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
}
#endif
#if NRF52_ERRATA_36_ENABLE_WORKAROUND
/* Workaround for Errata 36 "CLOCK: Some registers are not reset when expected" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_36()){
NRF_CLOCK->EVENTS_DONE = 0;
NRF_CLOCK->EVENTS_CTTO = 0;
NRF_CLOCK->CTIV = 0;
}
#endif
#if NRF52_ERRATA_37_ENABLE_WORKAROUND
/* Workaround for Errata 37 "RADIO: Encryption engine is slow by default" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_37()){
*(volatile uint32_t *)0x400005A0 = 0x3;
}
#endif
#if NRF52_ERRATA_57_ENABLE_WORKAROUND
/* Workaround for Errata 57 "NFCT: NFC Modulation amplitude" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_57()){
*(volatile uint32_t *)0x40005610 = 0x00000005;
*(volatile uint32_t *)0x40005688 = 0x00000001;
*(volatile uint32_t *)0x40005618 = 0x00000000;
*(volatile uint32_t *)0x40005614 = 0x0000003F;
}
#endif
#if NRF52_ERRATA_66_ENABLE_WORKAROUND
/* Workaround for Errata 66 "TEMP: Linearity specification not met with default settings" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_66()){
NRF_TEMP->A0 = NRF_FICR->TEMP.A0;
NRF_TEMP->A1 = NRF_FICR->TEMP.A1;
NRF_TEMP->A2 = NRF_FICR->TEMP.A2;
NRF_TEMP->A3 = NRF_FICR->TEMP.A3;
NRF_TEMP->A4 = NRF_FICR->TEMP.A4;
NRF_TEMP->A5 = NRF_FICR->TEMP.A5;
NRF_TEMP->B0 = NRF_FICR->TEMP.B0;
NRF_TEMP->B1 = NRF_FICR->TEMP.B1;
NRF_TEMP->B2 = NRF_FICR->TEMP.B2;
NRF_TEMP->B3 = NRF_FICR->TEMP.B3;
NRF_TEMP->B4 = NRF_FICR->TEMP.B4;
NRF_TEMP->B5 = NRF_FICR->TEMP.B5;
NRF_TEMP->T0 = NRF_FICR->TEMP.T0;
NRF_TEMP->T1 = NRF_FICR->TEMP.T1;
NRF_TEMP->T2 = NRF_FICR->TEMP.T2;
NRF_TEMP->T3 = NRF_FICR->TEMP.T3;
NRF_TEMP->T4 = NRF_FICR->TEMP.T4;
}
#endif
#if NRF52_ERRATA_98_ENABLE_WORKAROUND
/* Workaround for Errata 98 "NFCT: Not able to communicate with the peer" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_98()){
*(volatile uint32_t *)0x4000568Cul = 0x00038148ul;
}
#endif
#if NRF52_ERRATA_103_ENABLE_WORKAROUND && defined(CCM_MAXPACKETSIZE_MAXPACKETSIZE_Pos)
/* Workaround for Errata 103 "CCM: Wrong reset value of CCM MAXPACKETSIZE" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_103()){
NRF_CCM->MAXPACKETSIZE = 0xFBul;
}
#endif
#if NRF52_ERRATA_108_ENABLE_WORKAROUND
/* Workaround for Errata 108 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_108()){
*(volatile uint32_t *)0x40000EE4ul = *(volatile uint32_t *)0x10000258ul & 0x0000004Ful;
}
#endif
#if NRF52_ERRATA_115_ENABLE_WORKAROUND
/* Workaround for Errata 115 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_115()){
*(volatile uint32_t *)0x40000EE4 = (*(volatile uint32_t *)0x40000EE4 & 0xFFFFFFF0) | (*(uint32_t *)0x10000258 & 0x0000000F);
}
#endif
#if NRF52_ERRATA_120_ENABLE_WORKAROUND
/* Workaround for Errata 120 "QSPI: Data read or written is corrupted" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_120()){
*(volatile uint32_t *)0x40029640ul = 0x200ul;
}
#endif
#if NRF52_ERRATA_136_ENABLE_WORKAROUND
/* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_136()){
if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){
NRF_POWER->RESETREAS = ~POWER_RESETREAS_RESETPIN_Msk;
}
}
#endif
#if NRF52_ERRATA_182_ENABLE_WORKAROUND
/* Workaround for Errata 182 "RADIO: Fixes for anomalies #102, #106, and #107 do not take effect" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_182()){
*(volatile uint32_t *) 0x4000173C |= (0x1 << 10);
}
#endif
#if NRF52_ERRATA_217_ENABLE_WORKAROUND
/* Workaround for Errata 217 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
for your device located at https://infocenter.nordicsemi.com/index.jsp */
if (nrf52_errata_217()){
*(volatile uint32_t *)0x40000EE4ul |= 0x0000000Ful;
}
#endif
/* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
* compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
* operations are not used in your code. */
#if (__FPU_USED == 1)
SCB->CPACR |= (3UL << 20) | (3UL << 22);
__DSB();
__ISB();
#endif
nrf52_handle_approtect();
#if NRF52_CONFIGURATION_249_ENABLE && (defined(NRF52805_XXAA) || defined(NRF52810_XXAA) || defined(NRF52811_XXAA))
if (nrf52_configuration_249() && (NRF_UICR->NRFMDK[0] == 0xFFFFFFFF || NRF_UICR->NRFMDK[1] == 0xFFFFFFFF))
{
nvmc_config(NVMC_CONFIG_WEN_Wen);
NRF_UICR->NRFMDK[0] = 0;
nvmc_wait();
NRF_UICR->NRFMDK[1] = 0;
nvmc_wait();
nvmc_config(NVMC_CONFIG_WEN_Ren);
}
#endif
/* Configure NFCT pins as GPIOs if NFCT is not to be used in your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined,
two GPIOs (see Product Specification to see which ones) will be reserved for NFC and will not be available as
normal GPIOs. */
#if defined (CONFIG_NFCT_PINS_AS_GPIOS) && defined(NFCT_PRESENT)
if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){
nvmc_config(NVMC_CONFIG_WEN_Wen);
NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
nvmc_wait();
nvmc_config(NVMC_CONFIG_WEN_Ren);
NVIC_SystemReset();
}
#endif
/* Configure GPIO pads as pPin Reset pin if Pin Reset capabilities desired. If CONFIG_GPIO_AS_PINRESET is not
defined, pin reset will not be available. One GPIO (see Product Specification to see which one) will then be
reserved for PinReset and not available as normal GPIO. */
#if defined (CONFIG_GPIO_AS_PINRESET)
if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){
nvmc_config(NVMC_CONFIG_WEN_Wen);
NRF_UICR->PSELRESET[0] = RESET_PIN;
nvmc_wait();
NRF_UICR->PSELRESET[1] = RESET_PIN;
nvmc_wait();
nvmc_config(NVMC_CONFIG_WEN_Ren);
NVIC_SystemReset();
}
#endif
/* When developing for nRF52810 on an nRF52832, or nRF52811 on an nRF52840,
make sure NFC pins are mapped as GPIO. */
#if defined (DEVELOP_IN_NRF52832) && defined(NRF52810_XXAA) \
|| defined (DEVELOP_IN_NRF52840) && defined(NRF52811_XXAA)
if ((*((uint32_t *)0x1000120C) & (1 << 0)) != 0){
nvmc_config(NVMC_CONFIG_WEN_Wen);
*((uint32_t *)0x1000120C) = 0;
nvmc_wait();
nvmc_config(NVMC_CONFIG_WEN_Ren);
NVIC_SystemReset();
}
#endif
SystemCoreClockUpdate();
}

14
ble_app_uart_c.eww

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace> <project>
<path>$WS_DIR$\pca10040\s132\iar\ble_app_uart_c_pca10040_s132.ewp</path>
</project> <project>
<path>$WS_DIR$\pca10056\s140\iar\ble_app_uart_c_pca10056_s140.ewp</path>
</project> <project>
<path>$WS_DIR$\pca10100\s122\iar\ble_app_uart_c_pca10100_s122.ewp</path>
</project> <project>
<path>$WS_DIR$\pca10100e\s122\iar\ble_app_uart_c_pca10100e_s122.ewp</path>
</project> <project>
<path>$WS_DIR$\pca10100e\s140\iar\ble_app_uart_c_pca10100e_s140.ewp</path>
</project> <batchBuild/>
</workspace>

3637
ble_app_uart_c_pca10100_s122.uvguix.h_zha
File diff suppressed because it is too large
View File

1132
ble_app_uart_c_pca10100_s122.uvoptx
File diff suppressed because it is too large
View File

7155
ble_app_uart_c_pca10100_s122.uvprojx
File diff suppressed because it is too large
View File

12041
config/sdk_config.h
File diff suppressed because it is too large
View File

708
main.c

@ -0,0 +1,708 @@
/**
* Copyright (c) 2016 - 2021, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "nordic_common.h"
#include "app_error.h"
#include "app_uart.h"
#include "ble_db_discovery.h"
#include "app_timer.h"
#include "app_util.h"
#include "bsp_btn_ble.h"
#include "ble.h"
#include "ble_gap.h"
#include "ble_hci.h"
#include "nrf_sdh.h"
#include "nrf_sdh_ble.h"
#include "nrf_sdh_soc.h"
#include "zble_nus_c.h"
#include "nrf_ble_gatt.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_ble_scan.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#define APP_BLE_CONN_CFG_TAG 1 /**< Tag that refers to the BLE stack configuration set with @ref sd_ble_cfg_set. The default tag is @ref BLE_CONN_CFG_TAG_DEFAULT. */
#define APP_BLE_OBSERVER_PRIO 3 /**< BLE observer priority of the application. There is no need to modify this value. */
#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define ECHOBACK_BLE_UART_DATA 0 /**< Echo the UART data that is received over the Nordic UART Service (NUS) back to the sender. */
BLE_NUS_C_DEF(m_ble_nus_c); /**< BLE Nordic UART Service (NUS) client instance. */
NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */
BLE_DB_DISCOVERY_DEF(m_db_disc); /**< Database discovery module instance. */
NRF_BLE_SCAN_DEF(m_scan); /**< Scanning Module instance. */
NRF_BLE_GQ_DEF(m_ble_gatt_queue, /**< BLE GATT Queue instance. */
NRF_SDH_BLE_CENTRAL_LINK_COUNT,
NRF_BLE_GQ_QUEUE_SIZE);
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
/**@brief NUS UUID. */
static ble_uuid_t const m_nus_uuid =
{
.uuid = BLE_UUID_NUS_SERVICE,
.type = NUS_SERVICE_UUID_TYPE
};
/**@brief Function for handling asserts in the SoftDevice.
*
* @details This function is called in case of an assert in the SoftDevice.
*
* @warning This handler is only an example and is not meant for the final product. You need to analyze
* how your product is supposed to react in case of assert.
* @warning On assert from the SoftDevice, the system can only recover on reset.
*
* @param[in] line_num Line number of the failing assert call.
* @param[in] p_file_name File name of the failing assert call.
*/
void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
{
app_error_handler(0xDEADBEEF, line_num, p_file_name);
}
/**@brief Function for handling the Nordic UART Service Client errors.
*
* @param[in] nrf_error Error code containing information about what went wrong.
*/
static void nus_error_handler(uint32_t nrf_error)
{
APP_ERROR_HANDLER(nrf_error);
}
/**@brief Function to start scanning. */
static void scan_start(void)
{
ret_code_t ret;
ret = nrf_ble_scan_start(&m_scan);
APP_ERROR_CHECK(ret);
ret = bsp_indication_set(BSP_INDICATE_SCANNING);
APP_ERROR_CHECK(ret);
}
/**@brief Function for handling Scanning Module events.
*/
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
ret_code_t err_code;
switch(p_scan_evt->scan_evt_id)
{
case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
{
err_code = p_scan_evt->params.connecting_err.err_code;
APP_ERROR_CHECK(err_code);
} break;
case NRF_BLE_SCAN_EVT_CONNECTED:
{
ble_gap_evt_connected_t const * p_connected =
p_scan_evt->params.connected.p_connected;
// Scan is automatically stopped by the connection.
NRF_LOG_INFO("Connecting to target %02x%02x%02x%02x%02x%02x",
p_connected->peer_addr.addr[0],
p_connected->peer_addr.addr[1],
p_connected->peer_addr.addr[2],
p_connected->peer_addr.addr[3],
p_connected->peer_addr.addr[4],
p_connected->peer_addr.addr[5]
);
} break;
case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
{
NRF_LOG_INFO("Scan timed out.");
scan_start();
} break;
default:
break;
}
}
/**@brief Function for initializing the scanning and setting the filters.
*/
static void scan_init(void)
{
ret_code_t err_code;
nrf_ble_scan_init_t init_scan;
memset(&init_scan, 0, sizeof(init_scan));
init_scan.connect_if_match = true;
init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &m_nus_uuid);
APP_ERROR_CHECK(err_code);
err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_UUID_FILTER, false);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling database discovery events.
*
* @details This function is a callback function to handle events from the database discovery module.
* Depending on the UUIDs that are discovered, this function forwards the events
* to their respective services.
*
* @param[in] p_event Pointer to the database discovery event.
*/
static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
{
ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt);
}
/**@brief Function for handling characters received by the Nordic UART Service (NUS).
*
* @details This function takes a list of characters of length data_len and prints the characters out on UART.
* If @ref ECHOBACK_BLE_UART_DATA is set, the data is sent back to sender.
*/
static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
{
ret_code_t ret_val;
NRF_LOG_DEBUG("Receiving data.");
NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);
// app_uart_put(0x5A);
// app_uart_put(data_len);
for (uint32_t i = 0; i < data_len; i++)
{
do
{
ret_val = app_uart_put(p_data[i]);
if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
{
NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
APP_ERROR_CHECK(ret_val);
}
} while (ret_val == NRF_ERROR_BUSY);
}
app_uart_put(0x5A);
app_uart_put(0xA5);
// if (p_data[data_len-1] == '\r')
// {
// while (app_uart_put('\n') == NRF_ERROR_BUSY);
// }
if (ECHOBACK_BLE_UART_DATA)
{
// Send data back to the peripheral.
do
{
ret_val = ble_nus_c_string_send(&m_ble_nus_c, p_data, data_len);
if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
{
NRF_LOG_ERROR("Failed sending NUS message. Error 0x%x. ", ret_val);
APP_ERROR_CHECK(ret_val);
}
} while (ret_val == NRF_ERROR_BUSY);
}
}
/**@brief Function for handling app_uart events.
*
* @details This function receives a single character from the app_uart module and appends it to
* a string. The string is sent over BLE when the last character received is a
* 'new line' '\n' (hex 0x0A) or if the string reaches the maximum data length.
*/
static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
static uint16_t data_array_index = 0;
// static uint32_t
void uart_event_handle(app_uart_evt_t * p_event)
{
uint32_t ret_val;
switch (p_event->evt_type)
{
/**@snippet [Handling data from UART] */
case APP_UART_DATA_READY:
UNUSED_VARIABLE(app_uart_get(&data_array[data_array_index]));
data_array_index++;
if (
data_array_index >= (m_ble_nus_max_data_len))
{
NRF_LOG_DEBUG("Ready to send data over BLE NUS");
NRF_LOG_HEXDUMP_DEBUG(data_array, data_array_index);
do
{
ret_val = ble_nus_c_string_send(&m_ble_nus_c, data_array, data_array_index);
if ( (ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES) )
{
APP_ERROR_CHECK(ret_val);
}
} while (ret_val == NRF_ERROR_RESOURCES);
data_array_index = 0;
}
break;
/**@snippet [Handling data from UART] */
case APP_UART_COMMUNICATION_ERROR:
NRF_LOG_ERROR("Communication error occurred while handling UART.");
APP_ERROR_HANDLER(p_event->data.error_communication);
break;
case APP_UART_FIFO_ERROR:
NRF_LOG_ERROR("Error occurred in FIFO module used by UART.");
APP_ERROR_HANDLER(p_event->data.error_code);
break;
default:
break;
}
}
/**@brief Callback handling Nordic UART Service (NUS) client events.
*
* @details This function is called to notify the application of NUS client events.
*
* @param[in] p_ble_nus_c NUS client handle. This identifies the NUS client.
* @param[in] p_ble_nus_evt Pointer to the NUS client event.
*/
/**@snippet [Handling events from the ble_nus_c module] */
static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
{
ret_code_t err_code;
switch (p_ble_nus_evt->evt_type)
{
case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
NRF_LOG_INFO("Discovery complete.");
err_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &p_ble_nus_evt->handles);
APP_ERROR_CHECK(err_code);
err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("Connected to device with Nordic UART Service.");
break;
case BLE_NUS_C_EVT_NUS_TX_EVT:
ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
break;
// case BLE_NUS_C_EVT_NUS_TX_BLOCK_EVT:
// ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);
// break;
case BLE_NUS_C_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected.");
scan_start();
break;
}
}
/**@snippet [Handling events from the ble_nus_c module] */
/**
* @brief Function for handling shutdown events.
*
* @param[in] event Shutdown type.
*/
static bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
ret_code_t err_code;
err_code = bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);
switch (event)
{
case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
// Prepare wakeup buttons.
err_code = bsp_btn_ble_sleep_mode_prepare();
APP_ERROR_CHECK(err_code);
break;
default:
break;
}
return true;
}
NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, APP_SHUTDOWN_HANDLER_PRIORITY);
/**@brief Function for handling BLE events.
*
* @param[in] p_ble_evt Bluetooth stack event.
* @param[in] p_context Unused.
*/
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
ret_code_t err_code;
ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
APP_ERROR_CHECK(err_code);
err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
APP_ERROR_CHECK(err_code);
// start discovery of services. The NUS Client waits for a discovery result
err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
APP_ERROR_CHECK(err_code);
break;
case BLE_GAP_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%x",
p_gap_evt->conn_handle,
p_gap_evt->params.disconnected.reason);
break;
case BLE_GAP_EVT_TIMEOUT:
if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
{
NRF_LOG_INFO("Connection Request timed out.");
}
break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported.
err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
APP_ERROR_CHECK(err_code);
break;
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
// Accepting parameters requested by peer.
err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
&p_gap_evt->params.conn_param_update_request.conn_params);
APP_ERROR_CHECK(err_code);
break;
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
} break;
case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
NRF_LOG_DEBUG("GATT Client Timeout.");
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
NRF_LOG_DEBUG("GATT Server Timeout.");
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;
default:
break;
}
}
/**@brief Function for initializing the BLE stack.
*
* @details Initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// Register a handler for BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
if (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)
{
NRF_LOG_INFO("ATT MTU exchange completed.");
m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
NRF_LOG_INFO("Ble NUS max data length set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
}
}
/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
ret_code_t err_code;
err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
APP_ERROR_CHECK(err_code);
err_code = nrf_ble_gatt_att_mtu_central_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling events from the BSP module.
*
* @param[in] event Event generated by button press.
*/
void bsp_event_handler(bsp_event_t event)
{
ret_code_t err_code;
switch (event)
{
case BSP_EVENT_SLEEP:
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
break;
case BSP_EVENT_DISCONNECT:
err_code = sd_ble_gap_disconnect(m_ble_nus_c.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
break;
default:
break;
}
}
/**@brief Function for initializing the UART. */
static void uart_init(void)
{
ret_code_t err_code;
app_uart_comm_params_t const comm_params =
{
.rx_pin_no = RX_PIN_NUMBER,
.tx_pin_no = TX_PIN_NUMBER,
.rts_pin_no = RTS_PIN_NUMBER,
.cts_pin_no = CTS_PIN_NUMBER,
.flow_control = APP_UART_FLOW_CONTROL_DISABLED,
.use_parity = false,
.baud_rate = UART_BAUDRATE_BAUDRATE_Baud921600
};
APP_UART_FIFO_INIT(&comm_params,
UART_RX_BUF_SIZE,
UART_TX_BUF_SIZE,
uart_event_handle,
APP_IRQ_PRIORITY_LOWEST,
err_code);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the Nordic UART Service (NUS) client. */
static void nus_c_init(void)
{
ret_code_t err_code;
ble_nus_c_init_t init;
init.evt_handler = ble_nus_c_evt_handler;
init.error_handler = nus_error_handler;
init.p_gatt_queue = &m_ble_gatt_queue;
err_code = ble_nus_c_init(&m_ble_nus_c, &init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing buttons and leds. */
static void buttons_leds_init(void)
{
ret_code_t err_code;
bsp_event_t startup_event;
err_code = bsp_init(BSP_INIT_LEDS, bsp_event_handler);
APP_ERROR_CHECK(err_code);
err_code = bsp_btn_ble_init(NULL, &startup_event);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the timer. */
static void timer_init(void)
{
ret_code_t err_code = app_timer_init();
APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the nrf log module. */
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
/**@brief Function for initializing power management.
*/
static void power_management_init(void)
{
ret_code_t err_code;
err_code = nrf_pwr_mgmt_init();
APP_ERROR_CHECK(err_code);
}
/** @brief Function for initializing the database discovery module. */
static void db_discovery_init(void)
{
ble_db_discovery_init_t db_init;
memset(&db_init, 0, sizeof(ble_db_discovery_init_t));
db_init.evt_handler = db_disc_handler;
db_init.p_gatt_queue = &m_ble_gatt_queue;
ret_code_t err_code = ble_db_discovery_init(&db_init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling the idle state (main loop).
*
* @details Handles any pending log operations, then sleeps until the next event occurs.
*/
static void idle_state_handle(void)
{
if (NRF_LOG_PROCESS() == false)
{
nrf_pwr_mgmt_run();
}
}
APP_TIMER_DEF(m_uart_send_tmr); // ״̬»úÇý¯¨Ê±Æ÷
static void uart_send_tmr_cb(void* p_context) { //
static uint32_t last_data_array_index;
ret_code_t ret_val;
if (data_array_index != 0 && data_array_index == last_data_array_index) {
do {
ret_val = ble_nus_c_string_send(&m_ble_nus_c, data_array, data_array_index);
if ((ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES)) {
APP_ERROR_CHECK(ret_val);
}
} while (ret_val == NRF_ERROR_RESOURCES);
data_array_index = 0;
last_data_array_index = 0;
}
last_data_array_index = data_array_index;
}
int main(void)
{
// Initialize.
log_init();
timer_init();
uart_init();
buttons_leds_init();
db_discovery_init();
power_management_init();
ble_stack_init();
gatt_init();
nus_c_init();
scan_init();
app_timer_create(&m_uart_send_tmr, APP_TIMER_MODE_REPEATED, uart_send_tmr_cb);
app_timer_start(m_uart_send_tmr, APP_TIMER_TICKS(2), NULL);
// app_uart_put(1);
// Start execution.
printf("BLE UART central example started.\r\n");
NRF_LOG_INFO("BLE UART central example started.");
scan_start();
// Enter main loop.
for (;;)
{
idle_state_handle();
}
}

302
zble_nus_c.c

@ -0,0 +1,302 @@
/**
* Copyright (c) 2012 - 2021, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(BLE_NUS_C)
#include <stdlib.h>
#include "app_error.h"
#include "ble.h"
#include "ble_gattc.h"
#include "ble_srv_common.h"
#include "zble_nus_c.h"
#define NRF_LOG_MODULE_NAME ble_nus_c
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
/**@brief Function for intercepting the errors of GATTC and the BLE GATT Queue.
*
* @param[in] nrf_error Error code.
* @param[in] p_ctx Parameter from the event handler.
* @param[in] conn_handle Connection handle.
*/
static void gatt_error_handler(uint32_t nrf_error, void *p_ctx, uint16_t conn_handle) {
ble_nus_c_t *p_ble_nus_c = (ble_nus_c_t *)p_ctx;
NRF_LOG_DEBUG("A GATT Client error has occurred on conn_handle: 0X%X", conn_handle);
if (p_ble_nus_c->error_handler != NULL) {
p_ble_nus_c->error_handler(nrf_error);
}
}
void ble_nus_c_on_db_disc_evt(ble_nus_c_t *p_ble_nus_c, ble_db_discovery_evt_t *p_evt) {
ble_nus_c_evt_t nus_c_evt;
memset(&nus_c_evt, 0, sizeof(ble_nus_c_evt_t));
ble_gatt_db_char_t *p_chars = p_evt->params.discovered_db.charateristics;
// Check if the NUS was discovered.
if ((p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE) && (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_NUS_SERVICE) && (p_evt->params.discovered_db.srv_uuid.type == p_ble_nus_c->uuid_type)) {
for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++) {
switch (p_chars[i].characteristic.uuid.uuid) {
case BLE_UUID_NUS_RX_CHARACTERISTIC:
nus_c_evt.handles.nus_rx_handle = p_chars[i].characteristic.handle_value;
break;
case BLE_UUID_NUS_TX_CHARACTERISTIC:
nus_c_evt.handles.nus_tx_handle = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_tx_cccd_handle = p_chars[i].cccd_handle;
break;
case BLE_UUID_NUS_TX_CHARACTERISTIC_2:
nus_c_evt.handles.nus_tx_handle_2 = p_chars[i].characteristic.handle_value;
nus_c_evt.handles.nus_tx_cccd_handle_2 = p_chars[i].cccd_handle;
break;
default:
break;
}
}
if (p_ble_nus_c->evt_handler != NULL) {
nus_c_evt.conn_handle = p_evt->conn_handle;
nus_c_evt.evt_type = BLE_NUS_C_EVT_DISCOVERY_COMPLETE;
p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
}
}
}
/**@brief Function for handling Handle Value Notification received from the SoftDevice.
*
* @details This function uses the Handle Value Notification received from the SoftDevice
* and checks if it is a notification of the NUS TX characteristic from the peer.
* If it is, this function decodes the data and sends it to the application.
*
* @param[in] p_ble_nus_c Pointer to the NUS Client structure.
* @param[in] p_ble_evt Pointer to the BLE event received.
*/
static void on_hvx(ble_nus_c_t *p_ble_nus_c, ble_evt_t const *p_ble_evt) {
// HVX can only occur from client sending.
if ((p_ble_nus_c->handles.nus_tx_handle != BLE_GATT_HANDLE_INVALID) && (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_nus_c->handles.nus_tx_handle) && (p_ble_nus_c->evt_handler != NULL)) {
ble_nus_c_evt_t ble_nus_c_evt;
ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_EVT;
ble_nus_c_evt.p_data = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;
p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
NRF_LOG_DEBUG("Client sending data.");
}
if ((p_ble_nus_c->handles.nus_tx_handle_2 != BLE_GATT_HANDLE_INVALID) && (p_ble_evt->evt.gattc_evt.params.hvx.handle == p_ble_nus_c->handles.nus_tx_handle_2) && (p_ble_nus_c->evt_handler != NULL)) {
ble_nus_c_evt_t ble_nus_c_evt;
// ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_EVT_2;
ble_nus_c_evt.evt_type = BLE_NUS_C_EVT_NUS_TX_EVT;
ble_nus_c_evt.p_data = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data;
ble_nus_c_evt.data_len = p_ble_evt->evt.gattc_evt.params.hvx.len;
p_ble_nus_c->evt_handler(p_ble_nus_c, &ble_nus_c_evt);
NRF_LOG_DEBUG("Client sending data.");
}
}
uint32_t ble_nus_c_init(ble_nus_c_t *p_ble_nus_c, ble_nus_c_init_t *p_ble_nus_c_init) {
uint32_t err_code;
ble_uuid_t uart_uuid;
ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
VERIFY_PARAM_NOT_NULL(p_ble_nus_c_init);
VERIFY_PARAM_NOT_NULL(p_ble_nus_c_init->p_gatt_queue);
err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_ble_nus_c->uuid_type);
VERIFY_SUCCESS(err_code);
uart_uuid.type = p_ble_nus_c->uuid_type;
uart_uuid.uuid = BLE_UUID_NUS_SERVICE;
p_ble_nus_c->conn_handle = BLE_CONN_HANDLE_INVALID;
p_ble_nus_c->evt_handler = p_ble_nus_c_init->evt_handler;
p_ble_nus_c->error_handler = p_ble_nus_c_init->error_handler;
p_ble_nus_c->handles.nus_tx_handle = BLE_GATT_HANDLE_INVALID;
p_ble_nus_c->handles.nus_tx_handle_2 = BLE_GATT_HANDLE_INVALID;
p_ble_nus_c->handles.nus_rx_handle = BLE_GATT_HANDLE_INVALID;
p_ble_nus_c->p_gatt_queue = p_ble_nus_c_init->p_gatt_queue;
return ble_db_discovery_evt_register(&uart_uuid);
}
void ble_nus_c_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) {
ble_nus_c_t *p_ble_nus_c = (ble_nus_c_t *)p_context;
if ((p_ble_nus_c == NULL) || (p_ble_evt == NULL)) {
return;
}
if ((p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID) || (p_ble_nus_c->conn_handle != p_ble_evt->evt.gap_evt.conn_handle)) {
return;
}
switch (p_ble_evt->header.evt_id) {
case BLE_GATTC_EVT_HVX:
on_hvx(p_ble_nus_c, p_ble_evt);
break;
case BLE_GAP_EVT_DISCONNECTED:
if (p_ble_evt->evt.gap_evt.conn_handle == p_ble_nus_c->conn_handle && p_ble_nus_c->evt_handler != NULL) {
ble_nus_c_evt_t nus_c_evt;
nus_c_evt.evt_type = BLE_NUS_C_EVT_DISCONNECTED;
p_ble_nus_c->conn_handle = BLE_CONN_HANDLE_INVALID;
p_ble_nus_c->evt_handler(p_ble_nus_c, &nus_c_evt);
}
break;
default:
// No implementation needed.
break;
}
}
/**@brief Function for creating a message for writing to the CCCD. */
static uint32_t cccd_configure(ble_nus_c_t *p_ble_nus_c, bool notification_enable) {
nrf_ble_gq_req_t cccd_req;
uint8_t cccd[BLE_CCCD_VALUE_LEN];
uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : 0;
memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));
cccd[0] = LSB_16(cccd_val);
cccd[1] = MSB_16(cccd_val);
cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
cccd_req.error_handler.cb = gatt_error_handler;
cccd_req.error_handler.p_ctx = p_ble_nus_c;
cccd_req.params.gattc_write.handle = p_ble_nus_c->handles.nus_tx_cccd_handle;
cccd_req.params.gattc_write.len = BLE_CCCD_VALUE_LEN;
cccd_req.params.gattc_write.offset = 0;
cccd_req.params.gattc_write.p_value = cccd;
cccd_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
cccd_req.params.gattc_write.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;
return nrf_ble_gq_item_add(p_ble_nus_c->p_gatt_queue, &cccd_req, p_ble_nus_c->conn_handle);
}
static uint32_t cccd_configure_2(ble_nus_c_t *p_ble_nus_c, bool notification_enable) {
nrf_ble_gq_req_t cccd_req;
uint8_t cccd[BLE_CCCD_VALUE_LEN];
uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : 0;
memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));
cccd[0] = LSB_16(cccd_val);
cccd[1] = MSB_16(cccd_val);
cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
cccd_req.error_handler.cb = gatt_error_handler;
cccd_req.error_handler.p_ctx = p_ble_nus_c;
cccd_req.params.gattc_write.handle = p_ble_nus_c->handles.nus_tx_cccd_handle_2;
cccd_req.params.gattc_write.len = BLE_CCCD_VALUE_LEN;
cccd_req.params.gattc_write.offset = 0;
cccd_req.params.gattc_write.p_value = cccd;
cccd_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
cccd_req.params.gattc_write.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;
return nrf_ble_gq_item_add(p_ble_nus_c->p_gatt_queue, &cccd_req, p_ble_nus_c->conn_handle);
}
uint32_t ble_nus_c_tx_notif_enable(ble_nus_c_t *p_ble_nus_c) {
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
if ((p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID) || (p_ble_nus_c->handles.nus_tx_cccd_handle == BLE_GATT_HANDLE_INVALID)) {
return NRF_ERROR_INVALID_STATE;
}
if ((p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID) || (p_ble_nus_c->handles.nus_tx_cccd_handle_2 == BLE_GATT_HANDLE_INVALID)) {
return NRF_ERROR_INVALID_STATE;
}
cccd_configure(p_ble_nus_c, true);
return cccd_configure_2(p_ble_nus_c, true);
}
uint32_t ble_nus_c_string_send(ble_nus_c_t *p_ble_nus_c, uint8_t *p_string, uint16_t length) {
VERIFY_PARAM_NOT_NULL(p_ble_nus_c);
nrf_ble_gq_req_t write_req;
memset(&write_req, 0, sizeof(nrf_ble_gq_req_t));
if (length > BLE_NUS_MAX_DATA_LEN) {
NRF_LOG_WARNING("Content too long.");
return NRF_ERROR_INVALID_PARAM;
}
if (p_ble_nus_c->conn_handle == BLE_CONN_HANDLE_INVALID) {
NRF_LOG_WARNING("Connection handle invalid.");
return NRF_ERROR_INVALID_STATE;
}
write_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
write_req.error_handler.cb = gatt_error_handler;
write_req.error_handler.p_ctx = p_ble_nus_c;
write_req.params.gattc_write.handle = p_ble_nus_c->handles.nus_rx_handle;
write_req.params.gattc_write.len = length;
write_req.params.gattc_write.offset = 0;
write_req.params.gattc_write.p_value = p_string;
write_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_CMD;
write_req.params.gattc_write.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE;
return nrf_ble_gq_item_add(p_ble_nus_c->p_gatt_queue, &write_req, p_ble_nus_c->conn_handle);
}
uint32_t ble_nus_c_handles_assign(ble_nus_c_t *p_ble_nus, uint16_t conn_handle, ble_nus_c_handles_t const *p_peer_handles) {
VERIFY_PARAM_NOT_NULL(p_ble_nus);
p_ble_nus->conn_handle = conn_handle;
if (p_peer_handles != NULL) {
p_ble_nus->handles.nus_tx_cccd_handle = p_peer_handles->nus_tx_cccd_handle;
p_ble_nus->handles.nus_tx_handle = p_peer_handles->nus_tx_handle;
p_ble_nus->handles.nus_tx_cccd_handle_2 = p_peer_handles->nus_tx_cccd_handle_2;
p_ble_nus->handles.nus_tx_handle_2 = p_peer_handles->nus_tx_handle_2;
p_ble_nus->handles.nus_rx_handle = p_peer_handles->nus_rx_handle;
}
return nrf_ble_gq_conn_handle_register(p_ble_nus->p_gatt_queue, conn_handle);
}
#endif

264
zble_nus_c.h

@ -0,0 +1,264 @@
/**
* Copyright (c) 2012 - 2021, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup ble_nus_c Nordic UART Service Client
* @{
* @ingroup ble_sdk_srv
* @brief Nordic UART Service Client module.
*
* @details This module contains the APIs and types exposed by the Nordic UART Service Client
* module. The application can use these APIs and types to perform the discovery of
* the Nordic UART Service at the peer and to interact with it.
*
* @note The application must register this module as the BLE event observer by using the
* NRF_SDH_BLE_OBSERVER macro. Example:
* @code
* ble_nus_c_t instance;
* NRF_SDH_BLE_OBSERVER(anything, BLE_NUS_C_BLE_OBSERVER_PRIO,
* ble_nus_c_on_ble_evt, &instance);
* @endcode
*
*/
#ifndef BLE_NUS_C_H__
#define BLE_NUS_C_H__
#include <stdbool.h>
#include <stdint.h>
#include "ble.h"
#include "ble_db_discovery.h"
#include "ble_gatt.h"
#include "ble_srv_common.h"
#include "nrf_ble_gq.h"
#include "nrf_sdh_ble.h"
#include "sdk_config.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Macro for defining a ble_nus_c instance.
*
* @param _name Name of the instance.
* @hideinitializer
*/
#define BLE_NUS_C_DEF(_name) \
static ble_nus_c_t _name; \
NRF_SDH_BLE_OBSERVER(_name##_obs, BLE_NUS_C_BLE_OBSERVER_PRIO, ble_nus_c_on_ble_evt, &_name)
/** @brief Macro for defining multiple ble_nus_c instances.
*
* @param _name Name of the array of instances.
* @param _cnt Number of instances to define.
* @hideinitializer
*/
#define BLE_NUS_C_ARRAY_DEF(_name, _cnt) \
static ble_nus_c_t _name[_cnt]; \
NRF_SDH_BLE_OBSERVERS(_name##_obs, BLE_NUS_C_BLE_OBSERVER_PRIO, ble_nus_c_on_ble_evt, &_name, _cnt)
#define NUS_BASE_UUID \
{ \
{ 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E } \
} /**< Used vendor-specific UUID. */
#define BLE_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */
#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */
#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */
#define BLE_UUID_NUS_TX_CHARACTERISTIC_2 0x0004 /**< The UUID of the TX Characteristic. */
#define OPCODE_LENGTH 1
#define HANDLE_LENGTH 2
/**@brief Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0)
#define BLE_NUS_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH)
#else
#define BLE_NUS_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH)
#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined.
#endif
/**@brief NUS Client event type. */
typedef enum {
BLE_NUS_C_EVT_DISCOVERY_COMPLETE, /**< Event indicating that the NUS service and its characteristics were found. */
BLE_NUS_C_EVT_NUS_TX_EVT, /**< Event indicating that the central received something from a peer. */
BLE_NUS_C_EVT_NUS_TX_EVT_2, /**< Event indicating that the central received something from a peer. */
BLE_NUS_C_EVT_DISCONNECTED /**< Event indicating that the NUS server disconnected. */
} ble_nus_c_evt_type_t;
/**@brief Handles on the connected peer device needed to interact with it. */
typedef struct {
uint16_t nus_tx_handle; /**< Handle of the NUS TX characteristic, as provided by a discovery. */
uint16_t nus_tx_cccd_handle; /**< Handle of the CCCD of the NUS TX characteristic, as provided by a discovery. */
uint16_t nus_tx_handle_2; /**< Handle of the NUS RX characteristic, as provided by a discovery. */
uint16_t nus_tx_cccd_handle_2; /**< Handle of the CCCD of the NUS TX characteristic, as provided by a discovery. */
uint16_t nus_rx_handle; /**< Handle of the NUS RX characteristic, as provided by a discovery. */
} ble_nus_c_handles_t;
/**@brief Structure containing the NUS event data received from the peer. */
typedef struct {
ble_nus_c_evt_type_t evt_type;
uint16_t conn_handle;
uint16_t max_data_len;
uint8_t* p_data;
uint16_t data_len;
ble_nus_c_handles_t handles; /**< Handles on which the Nordic UART service characteristics were discovered on the peer device. This is filled if the evt_type is @ref BLE_NUS_C_EVT_DISCOVERY_COMPLETE.*/
} ble_nus_c_evt_t;
// Forward declaration of the ble_nus_t type.
typedef struct ble_nus_c_s ble_nus_c_t;
/**@brief Event handler type.
*
* @details This is the type of the event handler that is to be provided by the application
* of this module to receive events.
*/
typedef void (*ble_nus_c_evt_handler_t)(ble_nus_c_t* p_ble_nus_c, ble_nus_c_evt_t const* p_evt);
/**@brief NUS Client structure. */
struct ble_nus_c_s {
uint8_t uuid_type; /**< UUID type. */
uint16_t conn_handle; /**< Handle of the current connection. Set with @ref ble_nus_c_handles_assign when connected. */
ble_nus_c_handles_t handles; /**< Handles on the connected peer device needed to interact with it. */
ble_nus_c_evt_handler_t evt_handler; /**< Application event handler to be called when there is an event related to the NUS. */
ble_srv_error_handler_t error_handler; /**< Function to be called in case of an error. */
nrf_ble_gq_t* p_gatt_queue; /**< Pointer to BLE GATT Queue instance. */
};
/**@brief NUS Client initialization structure. */
typedef struct {
ble_nus_c_evt_handler_t evt_handler; /**< Application event handler to be called when there is an event related to the NUS. */
ble_srv_error_handler_t error_handler; /**< Function to be called in case of an error. */
nrf_ble_gq_t* p_gatt_queue; /**< Pointer to BLE GATT Queue instance. */
} ble_nus_c_init_t;
/**@brief Function for initializing the Nordic UART client module.
*
* @details This function registers with the Database Discovery module
* for the NUS. The Database Discovery module looks for the presence
* of a NUS instance at the peer when a discovery is started.
*
* @param[in] p_ble_nus_c Pointer to the NUS client structure.
* @param[in] p_ble_nus_c_init Pointer to the NUS initialization structure that contains the
* initialization information.
*
* @retval NRF_SUCCESS If the module was initialized successfully.
* @retval err_code Otherwise, this function propagates the error code
* returned by the Database Discovery module API
* @ref ble_db_discovery_evt_register.
*/
uint32_t ble_nus_c_init(ble_nus_c_t* p_ble_nus_c, ble_nus_c_init_t* p_ble_nus_c_init);
/**@brief Function for handling events from the Database Discovery module.
*
* @details This function handles an event from the Database Discovery module, and determines
* whether it relates to the discovery of NUS at the peer. If it does, the function
* calls the application's event handler to indicate that NUS was
* discovered at the peer. The function also populates the event with service-related
* information before providing it to the application.
*
* @param[in] p_ble_nus_c Pointer to the NUS client structure.
* @param[in] p_evt Pointer to the event received from the Database Discovery module.
*/
void ble_nus_c_on_db_disc_evt(ble_nus_c_t* p_ble_nus_c, ble_db_discovery_evt_t* p_evt);
/**@brief Function for handling BLE events from the SoftDevice.
*
* @details This function handles the BLE events received from the SoftDevice. If a BLE
* event is relevant to the NUS module, the function uses the event's data to update
* internal variables and, if necessary, send events to the application.
*
* @param[in] p_ble_evt Pointer to the BLE event.
* @param[in] p_context Pointer to the NUS client structure.
*/
void ble_nus_c_on_ble_evt(ble_evt_t const* p_ble_evt, void* p_context);
/**@brief Function for requesting the peer to start sending notification of TX characteristic.
*
* @details This function enables notifications of the NUS TX characteristic at the peer
* by writing to the CCCD of the NUS TX characteristic.
*
* @param p_ble_nus_c Pointer to the NUS client structure.
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval err_code Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
*/
uint32_t ble_nus_c_tx_notif_enable(ble_nus_c_t* p_ble_nus_c);
/**@brief Function for sending a string to the server.
*
* @details This function writes the RX characteristic of the server.
*
* @param[in] p_ble_nus_c Pointer to the NUS client structure.
* @param[in] p_string String to be sent.
* @param[in] length Length of the string.
*
* @retval NRF_SUCCESS If the string was sent successfully.
* @retval err_code Otherwise, this API propagates the error code returned by function @ref nrf_ble_gq_item_add.
*/
uint32_t ble_nus_c_string_send(ble_nus_c_t* p_ble_nus_c, uint8_t* p_string, uint16_t length);
/**@brief Function for assigning handles to this instance of nus_c.
*
* @details Call this function when a link has been established with a peer to
* associate the link to this instance of the module. This makes it
* possible to handle several links and associate each link to a particular
* instance of this module. The connection handle and attribute handles are
* provided from the discovery event @ref BLE_NUS_C_EVT_DISCOVERY_COMPLETE.
*
* @param[in] p_ble_nus_c Pointer to the NUS client structure instance to associate with these
* handles.
* @param[in] conn_handle Connection handle to associated with the given NUS Instance.
* @param[in] p_peer_handles Attribute handles on the NUS server that you want this NUS client to
* interact with.
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval NRF_ERROR_NULL If a p_nus was a NULL pointer.
* @retval err_code Otherwise, this API propagates the error code returned
* by function @ref nrf_ble_gq_item_add.
*/
uint32_t ble_nus_c_handles_assign(ble_nus_c_t* p_ble_nus_c, uint16_t conn_handle, ble_nus_c_handles_t const* p_peer_handles);
#ifdef __cplusplus
}
#endif
#endif
Loading…
Cancel
Save