Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c846950983 | |||
| e9788b10df | |||
| c933e15399 | |||
| ef19d6b72f | |||
| 089114368e | |||
| 27560b237d | |||
| fe55899830 | |||
| 14a4dec57b | |||
| d3812a8b72 | |||
| df70d69851 | |||
| 440f443a99 | |||
| 32f5fee764 | |||
| 7fc5b54c47 | |||
| 370d6cc80f | |||
| d99848592b | |||
| 401c592281 | |||
| 415f4adfe9 | |||
| 9fc58b51fe | |||
| 508ac99c0d | |||
| 6158961dcf | |||
| be584e2900 |
@@ -2,3 +2,4 @@
|
||||
/.visualgdb/
|
||||
/VisualGDB/
|
||||
*.vgdbsettings.*.user
|
||||
/build/
|
||||
|
||||
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"cwd": "${workspaceRoot}",
|
||||
"executable": "${command:cmake.launchTargetPath}",
|
||||
"name": "(Ubuntu) launch & debug",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "jlink",
|
||||
"serverpath": "/opt/SEGGER/JLink/JLinkGDBServerCLExe",
|
||||
"serverArgs": [
|
||||
"-halt",
|
||||
"-ir",
|
||||
"-vd",
|
||||
"-strict",
|
||||
],
|
||||
"rttConfig": {
|
||||
"enabled": true,
|
||||
"address": "auto",
|
||||
"decoders": [
|
||||
{
|
||||
"label": "",
|
||||
"port": 0,
|
||||
"type": "console"
|
||||
}
|
||||
],
|
||||
},
|
||||
"armToolchainPath": "/opt/arm-none-eabi/bin",
|
||||
"device": "NRF52840_XXAA",
|
||||
"interface": "swd",
|
||||
"rtos": "FreeRTOS",
|
||||
"svdFile": "${workspaceRoot}/../bmd380_sdk/modules/nrfx/mdk/nrf52840.svd",
|
||||
"runToEntryPoint": "main",
|
||||
"preLaunchTask": "CMake: build"
|
||||
},
|
||||
{
|
||||
"cwd": "${workspaceRoot}",
|
||||
"executable": "${command:cmake.launchTargetPath}",
|
||||
"name": "(Windows) launch & debug",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "jlink",
|
||||
"serverpath": "C:/Program Files/SEGGER/JLink/JLinkGDBServerCL.exe",
|
||||
"serverArgs": [
|
||||
"-halt",
|
||||
"-ir",
|
||||
"-vd",
|
||||
"-strict",
|
||||
],
|
||||
"rttConfig": {
|
||||
"enabled": true,
|
||||
"address": "auto",
|
||||
"decoders": [
|
||||
{
|
||||
"label": "",
|
||||
"port": 0,
|
||||
"type": "console"
|
||||
}
|
||||
],
|
||||
},
|
||||
"armToolchainPath": "C:/sysgcc/arm-eabi/bin",
|
||||
"device": "NRF52840_XXAA",
|
||||
"interface": "swd",
|
||||
"rtos": "FreeRTOS",
|
||||
"svdFile": "${workspaceRoot}/../bmd380_sdk/modules/nrfx/mdk/nrf52840.svd",
|
||||
"runToEntryPoint": "main",
|
||||
"preLaunchTask": "CMake: build"
|
||||
},
|
||||
]
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: build",
|
||||
"command": "build",
|
||||
"targets": [
|
||||
"all"
|
||||
],
|
||||
"preset": "${command:cmake.activeBuildPresetName}",
|
||||
"group": {
|
||||
"kind": "build"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake template build task"
|
||||
},
|
||||
{
|
||||
"type": "cmake",
|
||||
"label": "CMake: clean rebuild",
|
||||
"command": "cleanRebuild",
|
||||
"targets": [
|
||||
"all"
|
||||
],
|
||||
"group": {
|
||||
"isDefault": true,
|
||||
"kind": "build"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "CMake template clean rebuild task"
|
||||
}
|
||||
]
|
||||
}
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
cmake_minimum_required(VERSION 3.15.3)
|
||||
|
||||
# Verbose output (optional)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
# Toolchain must be set before project()
|
||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/cmake/arm-none-eabi-gcc.cmake)
|
||||
include(${CMAKE_TOOLCHAIN_FILE})
|
||||
|
||||
# Project setup
|
||||
project(bmd380_central
|
||||
VERSION 1.0.0
|
||||
LANGUAGES C ASM
|
||||
)
|
||||
set(EXECUTABLE ${PROJECT_NAME}.elf)
|
||||
set(NRF_SDK_DIR ${CMAKE_SOURCE_DIR}/../bmd380_sdk)
|
||||
#set(LINKER_FILE ${CMAKE_SOURCE_DIR}/linkscripts/nRF52840_XXAA_s140.lds)
|
||||
set(LINKER_FILE ${CMAKE_SOURCE_DIR}/linkscripts/nRF52840_XXAA_S140_reserve.lds)
|
||||
set(LINKER_DIR ${CMAKE_SOURCE_DIR}/linkscripts)
|
||||
set(NRF_SDK_LINKER_DIR ${NRF_SDK_DIR}/modules/nrfx/mdk)
|
||||
set(SD_LINKER_DIR ${CMAKE_SOURCE_DIR}/SoftdeviceLibraries/hard)
|
||||
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
# Define the build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
|
||||
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
|
||||
|
||||
set(COMMON_COMPILE_OPT
|
||||
-mcpu=cortex-m4
|
||||
-mfpu=fpv4-sp-d16
|
||||
-mfloat-abi=hard
|
||||
-mthumb
|
||||
-fdata-sections
|
||||
-ffunction-sections
|
||||
-Wall
|
||||
-Os
|
||||
-g3
|
||||
-std=gnu99
|
||||
-Wno-unused-variable
|
||||
-Wno-pointer-sign
|
||||
-Wno-array-bounds
|
||||
)
|
||||
|
||||
set(COMMON_COMPILE_DEF
|
||||
-DDEBUG=1
|
||||
-DNRF52840_XXAA
|
||||
-DS140_reserve
|
||||
-DCONFIG_GPIO_AS_PIN
|
||||
-DRESETHNRF_DFU_SETTINGS_VERSION=2
|
||||
-DNRF_SD_BLE_API_VERSION=7
|
||||
-D__STACK_SIZE=1024
|
||||
-D__HEAP_SIZE=1024
|
||||
-DARM_MATH_CM4
|
||||
-DSOFTDEVICE_PRESENT
|
||||
-DUSE_APP_CONFIG
|
||||
)
|
||||
|
||||
set(COMMON_COMPILE_INC
|
||||
${ARM_TOOLCHAIN_DIR}/../arm-none-eabi/include
|
||||
${CMAKE_SOURCE_DIR}/app
|
||||
${NRF_SDK_DIR}/components/ble/ble_db_discovery
|
||||
${NRF_SDK_DIR}/components/ble/ble_services/ble_dis
|
||||
${NRF_SDK_DIR}/components/ble/ble_services/ble_dis_c
|
||||
${NRF_SDK_DIR}/components/ble/common/
|
||||
${NRF_SDK_DIR}/components/ble/nrf_ble_gatt
|
||||
${NRF_SDK_DIR}/components/ble/nrf_ble_gq
|
||||
${NRF_SDK_DIR}/components/ble/nrf_ble_scan
|
||||
${NRF_SDK_DIR}/components/libraries/atomic
|
||||
${NRF_SDK_DIR}/components/libraries/atomic_flags
|
||||
${NRF_SDK_DIR}/components/libraries/balloc
|
||||
${NRF_SDK_DIR}/components/libraries/delay
|
||||
${NRF_SDK_DIR}/components/libraries/experimental_section_vars
|
||||
${NRF_SDK_DIR}/components/libraries/log
|
||||
${NRF_SDK_DIR}/components/libraries/log/src
|
||||
${NRF_SDK_DIR}/components/libraries/memobj
|
||||
${NRF_SDK_DIR}/components/libraries/queue
|
||||
${NRF_SDK_DIR}/components/libraries/ringbuf
|
||||
${NRF_SDK_DIR}/components/libraries/strerror
|
||||
${NRF_SDK_DIR}/components/libraries/util
|
||||
${NRF_SDK_DIR}/components/softdevice/common
|
||||
${NRF_SDK_DIR}/components/softdevice/mbr/headers
|
||||
${NRF_SDK_DIR}/components/softdevice/s140/headers
|
||||
${NRF_SDK_DIR}/components/toolchain/cmsis/include
|
||||
${NRF_SDK_DIR}/external/fprintf
|
||||
${NRF_SDK_DIR}/external/freertos/portable/CMSIS/nrf52
|
||||
${NRF_SDK_DIR}/external/freertos/portable/GCC/nrf52
|
||||
${NRF_SDK_DIR}/external/freertos/source/include
|
||||
${NRF_SDK_DIR}/external/segger_rtt
|
||||
${NRF_SDK_DIR}/integration/nrfx
|
||||
${NRF_SDK_DIR}/integration/nrfx/legacy
|
||||
${NRF_SDK_DIR}/modules/nrfx
|
||||
${NRF_SDK_DIR}/modules/nrfx/drivers/include
|
||||
${NRF_SDK_DIR}/modules/nrfx/hal
|
||||
${NRF_SDK_DIR}/modules/nrfx/mdk
|
||||
)
|
||||
|
||||
# ==========================
|
||||
# Prj Configuration
|
||||
# ==========================
|
||||
add_library(prj_config INTERFACE)
|
||||
target_include_directories(prj_config INTERFACE ${COMMON_COMPILE_INC})
|
||||
target_compile_definitions(prj_config INTERFACE ${COMMON_COMPILE_DEF})
|
||||
target_compile_options(prj_config INTERFACE ${COMMON_COMPILE_OPT})
|
||||
|
||||
# ====================================================
|
||||
# Add FreeRTOS kernel and portable layer
|
||||
# Add application source files as an OBJECT library
|
||||
# Add board support package (BSP) source files as an OBJECT library
|
||||
# ====================================================
|
||||
add_subdirectory(app)
|
||||
include(cmake/freertos.cmake)
|
||||
|
||||
# ==========================
|
||||
# Executable Target
|
||||
# ==========================
|
||||
add_executable(${EXECUTABLE}
|
||||
$<TARGET_OBJECTS:app>
|
||||
${NRF_SDK_DIR}/components/ble/ble_db_discovery/ble_db_discovery.c
|
||||
${NRF_SDK_DIR}/components/ble/ble_services/ble_dis_c/ble_dis_c.c
|
||||
${NRF_SDK_DIR}/components/ble/common/ble_advdata.c
|
||||
${NRF_SDK_DIR}/components/ble/common/ble_conn_params.c
|
||||
${NRF_SDK_DIR}/components/ble/common/ble_conn_state.c
|
||||
${NRF_SDK_DIR}/components/ble/nrf_ble_gatt/nrf_ble_gatt.c
|
||||
${NRF_SDK_DIR}/components/ble/nrf_ble_gq/nrf_ble_gq.c
|
||||
${NRF_SDK_DIR}/components/ble/nrf_ble_scan/nrf_ble_scan.c
|
||||
${NRF_SDK_DIR}/components/libraries/atomic/nrf_atomic.c
|
||||
${NRF_SDK_DIR}/components/libraries/atomic_flags/nrf_atflags.c
|
||||
${NRF_SDK_DIR}/components/libraries/balloc/nrf_balloc.c
|
||||
${NRF_SDK_DIR}/components/libraries/experimental_section_vars/nrf_section_iter.c
|
||||
${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_backend_rtt.c
|
||||
${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_backend_serial.c
|
||||
${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_default_backends.c
|
||||
${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_frontend.c
|
||||
${NRF_SDK_DIR}/components/libraries/log/src/nrf_log_str_formatter.c
|
||||
${NRF_SDK_DIR}/components/libraries/memobj/nrf_memobj.c
|
||||
${NRF_SDK_DIR}/components/libraries/queue/nrf_queue.c
|
||||
${NRF_SDK_DIR}/components/libraries/ringbuf/nrf_ringbuf.c
|
||||
${NRF_SDK_DIR}/components/libraries/strerror/nrf_strerror.c
|
||||
${NRF_SDK_DIR}/components/libraries/util/app_error.c
|
||||
${NRF_SDK_DIR}/components/libraries/util/app_error_handler_gcc.c
|
||||
${NRF_SDK_DIR}/components/libraries/util/app_error_weak.c
|
||||
${NRF_SDK_DIR}/components/libraries/util/app_util_platform.c
|
||||
${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh.c
|
||||
${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh_ble.c
|
||||
${NRF_SDK_DIR}/components/softdevice/common/nrf_sdh_freertos.c
|
||||
${NRF_SDK_DIR}/external/fprintf/nrf_fprintf.c
|
||||
${NRF_SDK_DIR}/external/fprintf/nrf_fprintf_format.c
|
||||
${NRF_SDK_DIR}/external/segger_rtt/SEGGER_RTT.c
|
||||
${NRF_SDK_DIR}/external/segger_rtt/SEGGER_RTT_printf.c
|
||||
${NRF_SDK_DIR}/integration/nrfx/legacy/nrf_drv_clock.c
|
||||
${NRF_SDK_DIR}/modules/nrfx/drivers/src/nrfx_clock.c
|
||||
${NRF_SDK_DIR}/modules/nrfx/mdk/gcc_startup_nrf52840.S
|
||||
${NRF_SDK_DIR}/modules/nrfx/mdk/system_nrf52.c
|
||||
)
|
||||
|
||||
target_include_directories(${EXECUTABLE} PRIVATE ${COMMON_COMPILE_INC})
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE ${COMMON_COMPILE_DEF})
|
||||
target_compile_options(${EXECUTABLE} PRIVATE ${COMMON_COMPILE_OPT})
|
||||
|
||||
# ==========================
|
||||
# Link configuration
|
||||
# ==========================
|
||||
|
||||
# Linker options (linker script and flags)
|
||||
target_link_options(${EXECUTABLE} PRIVATE
|
||||
-T${LINKER_FILE} # Linker script
|
||||
-L${SD_LINKER_DIR} # Linker library directory (SoftDevice)
|
||||
-L${NRF_SDK_LINKER_DIR} # Linker library directory (SDK)
|
||||
-L${LINKER_DIR} # Linker library directory
|
||||
-mcpu=cortex-m4 # CPU architecture
|
||||
-mfpu=fpv4-sp-d16 # Floating-point unit
|
||||
-mfloat-abi=hard
|
||||
-mthumb
|
||||
--specs=nano.specs # Use nano C library
|
||||
--specs=nosys.specs # Minimal syscall stubs
|
||||
-u _printf_float # Enable float support in printf
|
||||
-lc # Link C library
|
||||
-lm # Link math library
|
||||
-Wl,-Map=${PROJECT_NAME}.map,--cref # Generate memory map file
|
||||
-Wl,--gc-sections # Remove unused sections
|
||||
-Xlinker -print-memory-usage -Xlinker # Print memory usage after link
|
||||
)
|
||||
|
||||
# Link with logical (target-based) libraries
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE
|
||||
prj_config
|
||||
app
|
||||
freertos
|
||||
)
|
||||
|
||||
# ==========================
|
||||
# Post-build Actions
|
||||
# ==========================
|
||||
add_custom_command(TARGET ${EXECUTABLE}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_SIZE} ${EXECUTABLE}
|
||||
COMMENT "Print memory usage"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET ${EXECUTABLE}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} -O srec --srec-len=64 ${EXECUTABLE} ${PROJECT_NAME}.s19
|
||||
COMMAND ${CMAKE_OBJCOPY} -O ihex ${EXECUTABLE} ${PROJECT_NAME}.hex
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary ${EXECUTABLE} ${PROJECT_NAME}.bin
|
||||
COMMENT "Generate .s19, .hex, and .bin output files"
|
||||
)
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"version": 3,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Debug",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "RelWithDebInfo",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Release",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "MinSizeRel",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "MinSizeRel"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "Debug",
|
||||
"configurePreset": "Debug"
|
||||
},
|
||||
{
|
||||
"name": "RelWithDebInfo",
|
||||
"configurePreset": "RelWithDebInfo"
|
||||
},
|
||||
{
|
||||
"name": "Release",
|
||||
"configurePreset": "Release"
|
||||
},
|
||||
{
|
||||
"name": "MinSizeRel",
|
||||
"configurePreset": "MinSizeRel"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
REM Usage: ConvertSoftdevice.bat <Softdevice Name> <Intermediate Hex file name>
|
||||
set ARM_GCC_PREFIX=arm-none-eabi-
|
||||
cd /d %~dp0
|
||||
|
||||
if not exist soft mkdir soft
|
||||
if not exist hard mkdir hard
|
||||
|
||||
%ARM_GCC_PREFIX%objcopy.exe --gap-fill 0xFF -I ihex -O binary %2 %1_softdevice.bin
|
||||
|
||||
%ARM_GCC_PREFIX%gcc empty.c -c -o hard\%1_softdevice.o -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
%ARM_GCC_PREFIX%objcopy.exe --add-section .softdevice=%1_softdevice.bin --set-section-flags .softdevice=CONTENTS,ALLOC,LOAD,READONLY,CODE hard\%1_softdevice.o --remove-section .text --remove-section .data --remove-section .bss
|
||||
|
||||
%ARM_GCC_PREFIX%gcc empty.c -c -o soft\%1_softdevice.o -mcpu=cortex-m4 -mthumb -mfloat-abi=soft
|
||||
%ARM_GCC_PREFIX%objcopy.exe --add-section .softdevice=%1_softdevice.bin --set-section-flags .softdevice=CONTENTS,ALLOC,LOAD,READONLY,CODE soft\%1_softdevice.o --remove-section .text --remove-section .data --remove-section .bss
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
void dummyfunc()
|
||||
{
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.15.3)
|
||||
|
||||
file(GLOB_RECURSE APP_SOURCES "*.c")
|
||||
|
||||
add_library(app OBJECT ${APP_SOURCES})
|
||||
|
||||
target_link_libraries(app PRIVATE
|
||||
prj_config
|
||||
)
|
||||
@@ -63,7 +63,7 @@
|
||||
#define configTICK_RATE_HZ 1024
|
||||
#define configMAX_PRIORITIES ( 6 )
|
||||
#define configMINIMAL_STACK_SIZE ( 192 )
|
||||
#define configTOTAL_HEAP_SIZE ( 32 * 1024 )
|
||||
#define configTOTAL_HEAP_SIZE ( 64 * 1024 )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
@@ -15,9 +15,9 @@ extern "C"
|
||||
#define NRF_LOG_BACKEND_UART_ENABLED 0
|
||||
#define NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS 1
|
||||
#define NRF_LOG_BACKEND_RTT_TX_RETRY_CNT 3
|
||||
#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64
|
||||
#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 256
|
||||
#define NRF_LOG_DEFERRED 0
|
||||
#define NRF_LOG_USES_TIMESTAMP 0
|
||||
#define NRF_LOG_USES_TIMESTAMP 1
|
||||
#define NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 0
|
||||
|
||||
// SEGGER-RTT
|
||||
@@ -152,15 +152,15 @@ extern "C"
|
||||
// Priority for dispatching the BLE events to the Scanning Module.
|
||||
#define NRF_BLE_SCAN_OBSERVER_PRIO 1
|
||||
// Scanning interval. Determines the scan interval in units of 0.625 millisecond.
|
||||
#define NRF_BLE_SCAN_SCAN_INTERVAL 160
|
||||
#define NRF_BLE_SCAN_SCAN_INTERVAL 600
|
||||
// Duration of a scanning session in units of 10 ms. Range: 0x0001 - 0xFFFF (10 ms to 10.9225 ms). If set to 0x0000, the scanning continues until it is explicitly disabled.
|
||||
#define NRF_BLE_SCAN_SCAN_DURATION 0
|
||||
// Scanning window. Determines the scanning window in units of 0.625 millisecond.
|
||||
#define NRF_BLE_SCAN_SCAN_WINDOW 80
|
||||
#define NRF_BLE_SCAN_SCAN_WINDOW 400
|
||||
// Determines the supervision time-out in units of 10 millisecond.
|
||||
#define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 4000
|
||||
// Determines minimum connection interval in milliseconds.
|
||||
#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 7.5
|
||||
#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 8
|
||||
// Determines maximum connection interval in milliseconds.
|
||||
#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 20
|
||||
// Determines the slave latency in counts of connection events.
|
||||
@@ -168,9 +168,9 @@ extern "C"
|
||||
// Enabling filters for the Scanning Module.
|
||||
#define NRF_BLE_SCAN_FILTER_ENABLE 1
|
||||
// Number of filters for UUIDs.
|
||||
#define NRF_BLE_SCAN_UUID_CNT 0
|
||||
#define NRF_BLE_SCAN_UUID_CNT 1
|
||||
// Number of name filters.
|
||||
#define NRF_BLE_SCAN_NAME_CNT 2
|
||||
#define NRF_BLE_SCAN_NAME_CNT 0
|
||||
// Number of short name filters.
|
||||
#define NRF_BLE_SCAN_SHORT_NAME_CNT 0
|
||||
// Number of address filters.
|
||||
@@ -183,15 +183,15 @@ extern "C"
|
||||
|
||||
#define NRF_BLE_GQ_ENABLED 1
|
||||
// Default size of a single element in the pool of memory objects.
|
||||
#define NRF_BLE_GQ_DATAPOOL_ELEMENT_SIZE 20
|
||||
#define NRF_BLE_GQ_DATAPOOL_ELEMENT_SIZE 256
|
||||
// Default number of elements in the pool of memory objects.
|
||||
#define NRF_BLE_GQ_DATAPOOL_ELEMENT_COUNT 8
|
||||
#define NRF_BLE_GQ_DATAPOOL_ELEMENT_COUNT 32
|
||||
// Maximal size of the data inside GATTC write request (in bytes).
|
||||
#define NRF_BLE_GQ_GATTC_WRITE_MAX_DATA_LEN 2
|
||||
#define NRF_BLE_GQ_GATTC_WRITE_MAX_DATA_LEN 256
|
||||
// Maximal size of the data inside GATTC notification or indication request (in bytes).
|
||||
#define NRF_BLE_GQ_GATTS_HVX_MAX_DATA_LEN 16
|
||||
#define NRF_BLE_GQ_GATTS_HVX_MAX_DATA_LEN 256
|
||||
// Queue size for BLE GATT Queue module.
|
||||
#define NRF_BLE_GQ_QUEUE_SIZE 6
|
||||
#define NRF_BLE_GQ_QUEUE_SIZE 256
|
||||
// Priority with which BLE events are dispatched to the GATT Queue module.
|
||||
#define NRF_BLE_GQ_BLE_OBSERVER_PRIO 1
|
||||
|
||||
@@ -211,6 +211,17 @@ extern "C"
|
||||
// Enable GATT MTU exchange initiation
|
||||
#define NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED 1
|
||||
|
||||
// The maximum number of characteristics present in a service record
|
||||
#define BLE_GATT_DB_MAX_CHARS 16
|
||||
|
||||
// Custom UUID service & char
|
||||
#define BLE_UUID_CUSTOM_SERVICE 0xFFF0
|
||||
#define BLE_UUID_SIMPLEPROFILECHAR(n) (BLE_UUID_CUSTOM_SERVICE + n)
|
||||
|
||||
// Uart UUID service & char
|
||||
#define BLE_UUID_UART_SERVICE 0xFFF8
|
||||
#define BLE_UUID_UART_CHAR(n) (BLE_UUID_UART_SERVICE + n)
|
||||
|
||||
#define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -0,0 +1,431 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "ble_advdata.h"
|
||||
|
||||
#include "nrf_ble_gatt.h"
|
||||
#include "nrf_ble_scan.h"
|
||||
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_ble.h"
|
||||
#include "nrf_sdh_freertos.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "message_buffer.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint32_t uart_drv_rx(void *, uint32_t);
|
||||
extern uint32_t uart_drv_tx(void *, uint32_t);
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} ins_survive_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} ins_scan_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t addr_type;
|
||||
uint8_t addr[6];
|
||||
} ins_connect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} ins_disconnect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t handle;
|
||||
uint8_t write_data[255];
|
||||
} ins_write_char_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t handle;
|
||||
} ins_read_char_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
union
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t payload[255];
|
||||
};
|
||||
} raw;
|
||||
ins_survive_t survive;
|
||||
ins_scan_t scan;
|
||||
ins_connect_t connect;
|
||||
ins_disconnect_t disconnect;
|
||||
ins_write_char_t write_char;
|
||||
ins_read_char_t read_char;
|
||||
} host_ins_t;
|
||||
|
||||
#define EVT_ALL 0xFFFF
|
||||
#define EVT_MEM_RETURN_DATA 0x0010
|
||||
#define EVT_MEM_NOTIFY_HANDLE 0x0040
|
||||
#define EVT_MEM_UART_ROUTINE 0x0080
|
||||
#define EVT_MEM_INS_SCAN 0x0100
|
||||
#define EVT_MEM_INS_CONNECT 0x0200
|
||||
#define EVT_MEM_INS_WRITE 0x0400
|
||||
#define EVT_MEM_INS_READ 0x0800
|
||||
#define EVT_MEM_INS_DISCONNECT 0x1000
|
||||
#define EVT_MEM_INS_CHECK_SURVIVE 0x2000
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INS_IDLE = 0x00,
|
||||
INS_RESET = 0x01,
|
||||
INS_KEY = 0x02,
|
||||
INS_SCAN = 0x03,
|
||||
INS_SCAN_RESPONSE = 0x04,
|
||||
INS_CONNECT = 0x05,
|
||||
INS_WRITE_CHAR = 0x06,
|
||||
INS_READ_CHAR = 0x07,
|
||||
INS_DISCONNECT = 0x08,
|
||||
INS_PREPARE_CONNECT = 0x09,
|
||||
INS_CHECK_SURVIVE = 0x0A
|
||||
} ctrl_instr_t;
|
||||
|
||||
#define INST_SUFFIX 0xF1
|
||||
|
||||
static MessageBufferHandle_t host_cmd_msg;
|
||||
|
||||
static void success_ack(void)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x01, 0x03 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
|
||||
static void disconnect_and_timeout_ack(void)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x01, 0xFF };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
|
||||
static void on_ins_scan(ins_scan_t *p_ins)
|
||||
{
|
||||
extern void le_scan_start(void);
|
||||
le_scan_start();
|
||||
}
|
||||
|
||||
static void on_ins_connect(ins_connect_t *p_ins)
|
||||
{
|
||||
ble_gap_addr_t peer_addr;
|
||||
peer_addr.addr_id_peer = 0;
|
||||
peer_addr.addr_type = BLE_GAP_ADDR_TYPE_ANONYMOUS;
|
||||
peer_addr.addr[0] = p_ins->addr[5];
|
||||
peer_addr.addr[1] = p_ins->addr[4];
|
||||
peer_addr.addr[2] = p_ins->addr[3];
|
||||
peer_addr.addr[3] = p_ins->addr[2];
|
||||
peer_addr.addr[4] = p_ins->addr[1];
|
||||
peer_addr.addr[5] = p_ins->addr[0];
|
||||
|
||||
extern void le_scan_stop(void);
|
||||
le_scan_stop();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(3));
|
||||
|
||||
extern void le_scan_get_peer_addr(ble_gap_addr_t * p_peer_addr);
|
||||
le_scan_get_peer_addr(&peer_addr);
|
||||
|
||||
if (peer_addr.addr_type == BLE_GAP_ADDR_TYPE_ANONYMOUS)
|
||||
{
|
||||
extern void le_scan_start(void);
|
||||
le_scan_start();
|
||||
return;
|
||||
}
|
||||
|
||||
extern void le_gap_connet(ble_gap_addr_t * p_peer_addr);
|
||||
le_gap_connet(&peer_addr);
|
||||
|
||||
char rsp_buf[64];
|
||||
sprintf(rsp_buf, "%s: %02X:%02X:%02X:%02X:%02X:%02X", "Connect to", peer_addr.addr[5], peer_addr.addr[4], peer_addr.addr[3], peer_addr.addr[2], peer_addr.addr[1], peer_addr.addr[0]);
|
||||
NRF_LOG_INFO("%s", rsp_buf);
|
||||
}
|
||||
|
||||
static void on_ins_write_char(ins_write_char_t *p_ins)
|
||||
{
|
||||
uint16_t write_size = p_ins->len - sizeof(p_ins->handle) - 1;
|
||||
NRF_LOG_INFO("write handle: 0x%02X", p_ins->handle);
|
||||
{
|
||||
uint8_t *p_start = (void *)p_ins->write_data;
|
||||
uint32_t loop = write_size / 8;
|
||||
uint32_t remain = write_size % 8;
|
||||
for (int i = 0; i < loop; i++)
|
||||
{
|
||||
NRF_LOG_HEXDUMP_INFO(p_start, 8);
|
||||
p_start += 8;
|
||||
}
|
||||
if (remain)
|
||||
{
|
||||
NRF_LOG_HEXDUMP_INFO(p_start, remain);
|
||||
}
|
||||
}
|
||||
|
||||
extern ret_code_t le_gatt_c_write_req(uint32_t handle, void *, uint16_t);
|
||||
ret_code_t err_code = le_gatt_c_write_req(p_ins->handle, p_ins->write_data, write_size);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
success_ack();
|
||||
}
|
||||
|
||||
static void on_ins_read_char(ins_read_char_t *p_ins)
|
||||
{
|
||||
NRF_LOG_INFO("read handle: 0x%02X", p_ins->handle);
|
||||
extern ret_code_t le_gatt_c_read_char_req(uint32_t handle);
|
||||
ret_code_t ret_code = le_gatt_c_read_char_req(p_ins->handle);
|
||||
}
|
||||
|
||||
static void on_ins_disconnect(ins_disconnect_t *p_ins)
|
||||
{
|
||||
extern void le_gap_disconnet(uint16_t);
|
||||
le_gap_disconnet(0);
|
||||
}
|
||||
|
||||
static void on_ins_survive(ins_survive_t *p_ins)
|
||||
{
|
||||
success_ack();
|
||||
}
|
||||
|
||||
void host_read_char_cb(uint8_t *p_data, uint16_t len)
|
||||
{
|
||||
static union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t rsp_code;
|
||||
uint8_t payload[];
|
||||
};
|
||||
uint8_t arr[256];
|
||||
} read_char_rsp = {
|
||||
.rsp_code = 0x0004
|
||||
};
|
||||
|
||||
memcpy(read_char_rsp.payload, p_data, len);
|
||||
|
||||
uart_drv_tx(&read_char_rsp, sizeof(read_char_rsp.rsp_code) + len);
|
||||
|
||||
{
|
||||
uint8_t *p_start = p_data;
|
||||
uint32_t loop = len / 8;
|
||||
uint32_t remain = len % 8;
|
||||
for (int i = 0; i < loop; i++)
|
||||
{
|
||||
NRF_LOG_HEXDUMP_INFO(p_start, 8);
|
||||
p_start += 8;
|
||||
}
|
||||
if (remain)
|
||||
{
|
||||
NRF_LOG_HEXDUMP_INFO(p_start, remain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint16_t company_identifier;
|
||||
struct
|
||||
{
|
||||
const uint8_t company_code[5];
|
||||
const uint8_t hw_ver[4];
|
||||
const uint16_t battery_level;
|
||||
} __PACKED data;
|
||||
} manu_spec_data_t;
|
||||
|
||||
void host_scan_filter_match_cb(
|
||||
void *p_manu_spec_data,
|
||||
uint32_t manu_spec_data_len,
|
||||
char *p_device_name,
|
||||
uint32_t device_name_len,
|
||||
ble_gap_addr_t const *peer_addr,
|
||||
int16_t rssi)
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
uint16_t hci_packet_event;
|
||||
uint8_t len;
|
||||
uint8_t addr[6];
|
||||
uint8_t manu_spec_data[15];
|
||||
uint8_t dev_name[21];
|
||||
} __PACKED host_scan_rsp_t;
|
||||
|
||||
static host_scan_rsp_t host_scan_rsp;
|
||||
|
||||
memset(&host_scan_rsp, 0x00, sizeof(host_scan_rsp));
|
||||
|
||||
host_scan_rsp.hci_packet_event = 0x0004;
|
||||
|
||||
host_scan_rsp.len = sizeof(host_scan_rsp_t) - offsetof(host_scan_rsp_t, addr);
|
||||
|
||||
memcpy(host_scan_rsp.addr, peer_addr->addr, sizeof(host_scan_rsp.addr));
|
||||
|
||||
memcpy((void *)&host_scan_rsp.manu_spec_data, p_manu_spec_data, sizeof(host_scan_rsp.manu_spec_data));
|
||||
|
||||
memcpy((void *)host_scan_rsp.dev_name, p_device_name, device_name_len);
|
||||
|
||||
uart_drv_tx(&host_scan_rsp, sizeof(host_scan_rsp));
|
||||
|
||||
char peer_addr_str[(2 + 1) * BLE_GAP_ADDR_LEN + 1] = { 0 };
|
||||
sprintf(peer_addr_str, "%02X:%02X:%02X:%02X:%02X:%02X", host_scan_rsp.addr[5], host_scan_rsp.addr[4], host_scan_rsp.addr[3], host_scan_rsp.addr[2], host_scan_rsp.addr[1], host_scan_rsp.addr[0]);
|
||||
|
||||
NRF_LOG_INFO("Found: %s [%s, %ddb]",
|
||||
host_scan_rsp.dev_name,
|
||||
peer_addr_str,
|
||||
rssi);
|
||||
}
|
||||
|
||||
void host_connected_cb(void)
|
||||
{
|
||||
success_ack();
|
||||
}
|
||||
|
||||
static void host_cmd_exec_task(void *p_arg)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
static uint8_t buf[256] = { 0 };
|
||||
host_ins_t *p_ins = (void *)buf;
|
||||
|
||||
p_ins->raw.opcode = INS_IDLE;
|
||||
p_ins->raw.len = 0;
|
||||
|
||||
size_t recv = xMessageBufferReceive(host_cmd_msg, buf, sizeof(buf), portMAX_DELAY);
|
||||
|
||||
switch (p_ins->raw.opcode)
|
||||
{
|
||||
case INS_SCAN:
|
||||
on_ins_scan(&p_ins->scan);
|
||||
break;
|
||||
case INS_CONNECT:
|
||||
on_ins_connect(&p_ins->connect);
|
||||
break;
|
||||
case INS_WRITE_CHAR:
|
||||
on_ins_write_char(&p_ins->write_char);
|
||||
break;
|
||||
case INS_READ_CHAR:
|
||||
on_ins_read_char(&p_ins->read_char);
|
||||
break;
|
||||
case INS_DISCONNECT:
|
||||
on_ins_disconnect(&p_ins->disconnect);
|
||||
break;
|
||||
case INS_CHECK_SURVIVE:
|
||||
on_ins_survive(&p_ins->survive);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void host_cmd_recv_task(void *p_arg)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
static uint8_t buf[256];
|
||||
|
||||
uint32_t recv = uart_drv_rx(buf, sizeof(buf));
|
||||
uint32_t offset = 0;
|
||||
|
||||
while (offset < recv)
|
||||
{
|
||||
host_ins_t *p_ins = (void *)&buf[offset];
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
|
||||
if (p_ins->raw.payload[p_ins->raw.len] == INST_SUFFIX)
|
||||
{
|
||||
switch (p_ins->raw.opcode)
|
||||
{
|
||||
case INS_CHECK_SURVIVE:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_survive_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_survive_t);
|
||||
break;
|
||||
case INS_CONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_connect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_connect_t);
|
||||
break;
|
||||
case INS_DISCONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_disconnect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_disconnect_t);
|
||||
break;
|
||||
case INS_SCAN:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_scan_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_scan_t);
|
||||
break;
|
||||
case INS_READ_CHAR:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_read_char_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_read_char_t);
|
||||
break;
|
||||
case INS_WRITE_CHAR:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, offsetof(ins_write_char_t, handle) + p_ins->write_char.len, pdMS_TO_TICKS(0));
|
||||
offset += offsetof(ins_write_char_t, handle) + p_ins->write_char.len;
|
||||
break;
|
||||
default:
|
||||
offset++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void host_tasks_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
break;
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
case BLE_GAP_EVT_TIMEOUT:
|
||||
disconnect_and_timeout_ack();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void host_tasks_init(void)
|
||||
{
|
||||
host_cmd_msg = xMessageBufferCreate(1024);
|
||||
xTaskCreate(host_cmd_recv_task, "cmd_recv", 128, NULL, 3, NULL);
|
||||
xTaskCreate(host_cmd_exec_task, "cmd_exec", 512, NULL, 3, NULL);
|
||||
// Register a handler for BLE events.
|
||||
NRF_SDH_BLE_OBSERVER(m_tasks_observer, 3, host_tasks_handler, NULL);
|
||||
}
|
||||
@@ -4,6 +4,8 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "ble_db_discovery.h"
|
||||
#include "nrf_ble_gatt.h"
|
||||
#include "nrf_ble_gq.h"
|
||||
@@ -26,8 +28,10 @@ static void db_disc_handler(ble_db_discovery_evt_t *p_evt)
|
||||
NRF_LOG_INFO("BLE_DB_DISCOVERY_COMPLETE");
|
||||
extern void le_dis_c_on_db_disc_evt(ble_db_discovery_evt_t * p_evt);
|
||||
le_dis_c_on_db_disc_evt(p_evt);
|
||||
extern void le_eis_c_on_db_disc_evt(ble_db_discovery_evt_t * p_evt);
|
||||
le_eis_c_on_db_disc_evt(p_evt);
|
||||
extern void le_gatt_c_on_db_disc_evt(ble_db_discovery_evt_t * p_evt);
|
||||
le_gatt_c_on_db_disc_evt(p_evt);
|
||||
extern void le_uart_c_on_db_disc_evt(ble_db_discovery_evt_t * p_evt);
|
||||
le_uart_c_on_db_disc_evt(p_evt);
|
||||
break;
|
||||
case BLE_DB_DISCOVERY_ERROR:
|
||||
NRF_LOG_INFO("BLE_DB_DISCOVERY_ERROR");
|
||||
@@ -37,6 +41,8 @@ static void db_disc_handler(ble_db_discovery_evt_t *p_evt)
|
||||
break;
|
||||
case BLE_DB_DISCOVERY_AVAILABLE:
|
||||
NRF_LOG_INFO("BLE_DB_DISCOVERY_AVAILABLE");
|
||||
extern void host_connected_cb(void);
|
||||
host_connected_cb();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "ble_dis_c.h"
|
||||
|
||||
#include "ble_gattc.h"
|
||||
+51
-9
@@ -7,7 +7,8 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "app_config.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "apply_old_config.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
@@ -26,19 +27,55 @@ extern "C"
|
||||
}
|
||||
#endif
|
||||
|
||||
void le_gap_init(const char *device_name, uint16_t usAppearance)
|
||||
bool is_connected = false;
|
||||
|
||||
static void le_gap_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
// TODO...
|
||||
ret_code_t err_code;
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
is_connected = true;
|
||||
break;
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
is_connected = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void le_gap_connet(ble_gap_addr_t *p_peer_addr, nrf_ble_scan_t *p_scan)
|
||||
void le_gap_init(const char *device_name, uint16_t usAppearance)
|
||||
{
|
||||
// If address is correct, stop scanning and initiate connection with peripheral device.
|
||||
// Register a handler for BLE events.
|
||||
NRF_SDH_BLE_OBSERVER(m_gap_observer, 3, le_gap_handler, NULL);
|
||||
}
|
||||
|
||||
void le_gap_connet(ble_gap_addr_t *p_peer_addr)
|
||||
{
|
||||
if (is_connected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If address is correct, stop scanning and initiate connection with peripheral device.
|
||||
const ble_gap_conn_params_t conn_params = {
|
||||
.conn_sup_timeout =
|
||||
(uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS),
|
||||
.min_conn_interval =
|
||||
(uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS),
|
||||
.max_conn_interval =
|
||||
(uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS),
|
||||
.slave_latency =
|
||||
(uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY,
|
||||
};
|
||||
|
||||
extern ble_gap_scan_params_t *le_scan_params(void);
|
||||
ret_code_t err_code = sd_ble_gap_connect(p_peer_addr,
|
||||
&p_scan->scan_params,
|
||||
&p_scan->conn_params,
|
||||
le_scan_params(),
|
||||
&conn_params,
|
||||
APP_BLE_CONN_CFG_TAG);
|
||||
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
@@ -63,10 +100,15 @@ void le_gap_conn_param_update(uint16_t conn_handle)
|
||||
NRF_LOG_INFO("Central Preferred Connection Parameters.");
|
||||
// Set GAP Central Preferred Connection Parameters.
|
||||
ble_gap_conn_params_t const gap_conn_params = {
|
||||
.min_conn_interval = MSEC_TO_UNITS(8, UNIT_1_25_MS), /**< Minimum connection interval (7.5 ms) */
|
||||
.max_conn_interval = MSEC_TO_UNITS(20, UNIT_1_25_MS), /**< Maximum connection interval (20 ms). */
|
||||
.min_conn_interval = MSEC_TO_UNITS(8, UNIT_1_25_MS), /**< Minimum connection interval ( 7.5 ms) */
|
||||
.max_conn_interval = MSEC_TO_UNITS(10, UNIT_1_25_MS), /**< Maximum connection interval (10.0 ms). */
|
||||
.slave_latency = 8, /**< Slave latency. */
|
||||
.conn_sup_timeout = MSEC_TO_UNITS(10000, UNIT_10_MS) /**< Connection supervisory timeout (10s). */
|
||||
};
|
||||
sd_ble_gap_conn_param_update(conn_handle, &gap_conn_params);
|
||||
}
|
||||
|
||||
bool le_gap_is_connected(void)
|
||||
{
|
||||
return is_connected;
|
||||
}
|
||||
@@ -4,6 +4,8 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "nrf_ble_gq.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "app_config.h"
|
||||
#include "ble_db_discovery.h"
|
||||
#include "ble_gattc.h"
|
||||
#include "ble_srv_common.h"
|
||||
|
||||
#include "nrf_ble_gq.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_CNT 16
|
||||
|
||||
extern nrf_ble_gq_t *le_gap_queue(void);
|
||||
|
||||
struct ble_gatt_c_s
|
||||
{
|
||||
void (*evt_handler)(ble_evt_t const *p_ble_evt, void *p_context);
|
||||
uint16_t conn_handle;
|
||||
uint16_t char_handles[MAX_CHAR_CNT];
|
||||
};
|
||||
|
||||
uint16_t handle_mapping[MAX_CHAR_CNT];
|
||||
|
||||
typedef struct ble_gatt_c_s ble_gatt_c_t;
|
||||
|
||||
static ble_gatt_c_t m_gatt_c;
|
||||
|
||||
static void on_disconnected(ble_gatt_c_t *p_ble_gatt_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
p_ble_gatt_c->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
for (int i = 0; i < COUNTOF(p_ble_gatt_c->char_handles); i++)
|
||||
{
|
||||
p_ble_gatt_c->char_handles[i] = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t hvx_cnt = 0;
|
||||
static TickType_t hvx_begin = 0;
|
||||
static void on_connected(ble_gatt_c_t *p_ble_gatt_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
hvx_cnt = 0;
|
||||
hvx_begin = 0;
|
||||
extern void mem_board_reset(void);
|
||||
mem_board_reset();
|
||||
}
|
||||
|
||||
static void on_hvx(ble_gatt_c_t *p_ble_gatt_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
ble_gattc_evt_hvx_t *hvx = (void *)&p_ble_evt->evt.gattc_evt.params.hvx;
|
||||
uint32_t len = hvx->len;
|
||||
uint8_t *p = (uint8_t *)hvx->data;
|
||||
extern void mem_notify_cb(uint8_t * p, uint32_t len);
|
||||
mem_notify_cb(p, len);
|
||||
}
|
||||
|
||||
static void on_read_rsp(ble_gatt_c_t *p_le_gatt_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
extern void host_read_char_cb(uint8_t * p_data, uint16_t len);
|
||||
uint16_t handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle;
|
||||
|
||||
for (int i = 0; i < COUNTOF(p_le_gatt_c->char_handles); i++)
|
||||
{
|
||||
if (handle_mapping[i] == handle)
|
||||
{
|
||||
ble_gattc_evt_read_rsp_t const *p_response = &p_ble_evt->evt.gattc_evt.params.read_rsp;
|
||||
host_read_char_cb((uint8_t *)p_response->data, p_response->len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret_code_t le_gatt_ccdc_configure(uint16_t conn_handle, uint16_t char_handle, bool notification_enable)
|
||||
{
|
||||
if (conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
__BKPT(255);
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (char_handle == BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
__BKPT(255);
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
NRF_LOG_INFO("Configuring CCCD Handle = 0x%04X, Connection Handle = 0x%04X",
|
||||
char_handle + 1,
|
||||
conn_handle);
|
||||
|
||||
nrf_ble_gq_req_t cccd_req;
|
||||
uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INVALID;
|
||||
uint8_t cccd[BLE_CCCD_VALUE_LEN];
|
||||
|
||||
cccd[0] = LSB_16(cccd_val);
|
||||
cccd[1] = MSB_16(cccd_val);
|
||||
|
||||
memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
cccd_req.params.gattc_write.handle = char_handle + 1;
|
||||
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;
|
||||
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &cccd_req, conn_handle);
|
||||
}
|
||||
|
||||
static void le_gatt_c_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
ble_gatt_c_t *p_ble_gatt_c = (ble_gatt_c_t *)p_context;
|
||||
|
||||
if ((p_ble_gatt_c == NULL) || (p_ble_evt == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
on_disconnected(p_ble_gatt_c, p_ble_evt);
|
||||
break;
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
on_connected(p_ble_gatt_c, p_ble_evt);
|
||||
break;
|
||||
case BLE_GATTC_EVT_HVX:
|
||||
/*
|
||||
Handle Value Notification or Indication event.
|
||||
Confirm indication with @ref sd_ble_gattc_hv_confirm.
|
||||
See @ref ble_gattc_evt_hvx_t. */
|
||||
on_hvx(p_ble_gatt_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP:
|
||||
/*
|
||||
Read Response event.
|
||||
See @ref ble_gattc_evt_read_rsp_t. */
|
||||
on_read_rsp(p_ble_gatt_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
/*
|
||||
Primary Service Discovery Response event.
|
||||
See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_REL_DISC_RSP:
|
||||
/*
|
||||
Relationship Discovery Response event.
|
||||
See @ref ble_gattc_evt_rel_disc_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||
/*
|
||||
Characteristic Discovery Response event.
|
||||
See @ref ble_gattc_evt_char_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP:
|
||||
/*
|
||||
Descriptor Discovery Response event.
|
||||
See @ref ble_gattc_evt_desc_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP:
|
||||
/*
|
||||
Attribute Information Response event.
|
||||
See @ref ble_gattc_evt_attr_info_disc_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
|
||||
/*
|
||||
Read By UUID Response event.
|
||||
See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_VALS_READ_RSP:
|
||||
/*
|
||||
Read multiple Response event.
|
||||
See @ref ble_gattc_evt_char_vals_read_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_WRITE_RSP:
|
||||
/*
|
||||
Write Response event.
|
||||
See @ref ble_gattc_evt_write_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
|
||||
/*
|
||||
Exchange MTU Response event.
|
||||
See @ref ble_gattc_evt_exchange_mtu_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_TIMEOUT:
|
||||
/*
|
||||
Timeout event.
|
||||
See @ref ble_gattc_evt_timeout_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE:
|
||||
/*
|
||||
Write without Response transmission complete. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void le_gatt_c_cccd_timer_cb(TimerHandle_t xTimer)
|
||||
{
|
||||
xTimerStop(xTimer, pdMS_TO_TICKS(0));
|
||||
for (int i = 0; i < COUNTOF(m_gatt_c.char_handles); i++)
|
||||
{
|
||||
le_gatt_ccdc_configure(m_gatt_c.conn_handle, m_gatt_c.char_handles[i], true);
|
||||
}
|
||||
NRF_LOG_INFO("Enable notifications. ");
|
||||
}
|
||||
|
||||
static TimerHandle_t le_gatt_c_cccd_timer = NULL;
|
||||
|
||||
void le_gatt_c_init(void)
|
||||
{
|
||||
m_gatt_c.evt_handler = le_gatt_c_evt_handler;
|
||||
m_gatt_c.conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
for (int i = 0; i < COUNTOF(m_gatt_c.char_handles); i++)
|
||||
{
|
||||
m_gatt_c.char_handles[i] = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
ret_code_t err_code;
|
||||
uint8_t uuid_type;
|
||||
ble_uuid_t uuid = {
|
||||
.type = BLE_UUID_TYPE_BLE,
|
||||
.uuid = BLE_UUID_CUSTOM_SERVICE,
|
||||
};
|
||||
err_code = ble_db_discovery_evt_register(&uuid);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
NRF_SDH_BLE_OBSERVER(m_gatt_c_observer, BLE_DIS_C_BLE_OBSERVER_PRIO, le_gatt_c_evt_handler, &m_gatt_c);
|
||||
|
||||
le_gatt_c_cccd_timer = xTimerCreate("Timer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, le_gatt_c_cccd_timer_cb);
|
||||
}
|
||||
|
||||
void le_gatt_c_on_db_disc_evt(ble_db_discovery_evt_t *p_evt)
|
||||
{
|
||||
ble_gatt_db_char_t *p_chars = p_evt->params.discovered_db.charateristics;
|
||||
|
||||
// Check if the service discovery is necessary for the link and if the event handler is present.
|
||||
if (m_gatt_c.evt_handler == NULL || m_gatt_c.conn_handle == p_evt->conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the custom service was discovered.
|
||||
if ((p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_CUSTOM_SERVICE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE))
|
||||
{
|
||||
m_gatt_c.conn_handle = p_evt->conn_handle;
|
||||
|
||||
for (int i = 0; i < p_evt->params.discovered_db.char_count; i++)
|
||||
{
|
||||
for (int j = 0; j < COUNTOF(m_gatt_c.char_handles); j++)
|
||||
{
|
||||
if (p_chars[i].characteristic.uuid.uuid == BLE_UUID_SIMPLEPROFILECHAR(j + 1))
|
||||
{
|
||||
m_gatt_c.char_handles[j] = p_chars[i].characteristic.handle_value;
|
||||
handle_mapping[j] = m_gatt_c.char_handles[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void le_gatt_c_error_handler(uint32_t nrf_error, void *p_contex, uint16_t conn_handle)
|
||||
{
|
||||
UNUSED_PARAMETER(conn_handle);
|
||||
__BKPT(255);
|
||||
}
|
||||
|
||||
ret_code_t le_gatt_c_read_char_req(uint32_t handle)
|
||||
{
|
||||
ble_gatt_c_t *p_le_gatt_c = &m_gatt_c;
|
||||
|
||||
if (p_le_gatt_c->conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < COUNTOF(p_le_gatt_c->char_handles); i++)
|
||||
{
|
||||
if (handle_mapping[i] == handle)
|
||||
{
|
||||
nrf_ble_gq_req_t gq_req;
|
||||
memset(&gq_req, 0, sizeof(gq_req));
|
||||
gq_req.type = NRF_BLE_GQ_REQ_GATTC_READ;
|
||||
gq_req.error_handler.cb = le_gatt_c_error_handler;
|
||||
gq_req.error_handler.p_ctx = p_le_gatt_c;
|
||||
gq_req.params.gattc_read.handle = p_le_gatt_c->char_handles[i];
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &gq_req, p_le_gatt_c->conn_handle);
|
||||
}
|
||||
}
|
||||
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret_code_t le_gatt_c_write_req(uint32_t handle, uint8_t const *p_data, uint16_t len)
|
||||
{
|
||||
ble_gatt_c_t *p_le_gatt_c = &m_gatt_c;
|
||||
|
||||
if (p_le_gatt_c->conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < COUNTOF(p_le_gatt_c->char_handles); i++)
|
||||
{
|
||||
if (handle_mapping[i] == handle)
|
||||
{
|
||||
nrf_ble_gq_req_t gq_req;
|
||||
memset(&gq_req, 0, sizeof(gq_req));
|
||||
gq_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
gq_req.error_handler.cb = le_gatt_c_error_handler;
|
||||
gq_req.error_handler.p_ctx = p_le_gatt_c;
|
||||
gq_req.params.gattc_write.handle = p_le_gatt_c->char_handles[i];
|
||||
gq_req.params.gattc_write.p_value = p_data;
|
||||
gq_req.params.gattc_write.len = len;
|
||||
gq_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &gq_req, p_le_gatt_c->conn_handle);
|
||||
}
|
||||
else if (handle_mapping[i] + 1 == handle)
|
||||
{
|
||||
uint16_t enable = *(uint16_t *)p_data & 0x0001;
|
||||
return le_gatt_ccdc_configure(m_gatt_c.conn_handle, handle_mapping[i], enable);
|
||||
}
|
||||
}
|
||||
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "app_config.h"
|
||||
#include "apply_old_config.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_ble.h"
|
||||
#include "nrf_sdh_freertos.h"
|
||||
|
||||
#include "ble_advdata.h"
|
||||
#include "ble_gap.h"
|
||||
#include "nrf_ble_scan.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAX_DEV_NAME_LEN ((BLE_GAP_ADV_SET_DATA_SIZE_MAX + 1) - AD_DATA_OFFSET)
|
||||
|
||||
static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
|
||||
{
|
||||
// Initialize advertisement report for parsing.
|
||||
ret_code_t err_code;
|
||||
uint16_t offset = 0;
|
||||
void *p_manu_spec_data = NULL;
|
||||
char dev_name[MAX_DEV_NAME_LEN];
|
||||
memset(dev_name, 0x00, MAX_DEV_NAME_LEN);
|
||||
|
||||
// Search for advertising names.
|
||||
uint32_t device_name_len = ble_advdata_search(p_adv_report->data.p_data,
|
||||
p_adv_report->data.len,
|
||||
&offset,
|
||||
BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
|
||||
if (device_name_len)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)p_adv_report->data.p_data;
|
||||
memcpy(dev_name, &p[offset], device_name_len);
|
||||
}
|
||||
|
||||
// Search for advertising manufacturer spec data
|
||||
offset = 0;
|
||||
uint32_t manu_spec_data_len =
|
||||
ble_advdata_search(p_adv_report->data.p_data, p_adv_report->data.len, &offset, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA);
|
||||
|
||||
if (manu_spec_data_len)
|
||||
{
|
||||
p_manu_spec_data = &p_adv_report->data.p_data[offset];
|
||||
}
|
||||
|
||||
extern void host_scan_filter_match_cb(
|
||||
void *p_manu_spec_data,
|
||||
uint32_t manu_spec_data_len,
|
||||
char *p_device_name,
|
||||
uint32_t device_name_len,
|
||||
ble_gap_addr_t const *peer_addr,
|
||||
int16_t rssi);
|
||||
|
||||
host_scan_filter_match_cb(
|
||||
p_manu_spec_data,
|
||||
manu_spec_data_len,
|
||||
dev_name,
|
||||
device_name_len,
|
||||
&p_adv_report->peer_addr,
|
||||
p_adv_report->rssi);
|
||||
}
|
||||
|
||||
static uint8_t scan_buffer[BLE_GAP_SCAN_BUFFER_MAX];
|
||||
static ble_data_t const adv_report_buffer = { .p_data = scan_buffer,
|
||||
.len = BLE_GAP_SCAN_BUFFER_MAX };
|
||||
static ble_uuid_t const filter_uuid = { .type = BLE_UUID_TYPE_BLE, .uuid = 0xFFF0 };
|
||||
static uint64_t mac = 0;
|
||||
static uint32_t peer_addr_idx = 0;
|
||||
static ble_gap_addr_t peer_addr_list[16];
|
||||
|
||||
void le_scan_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
ble_gap_evt_adv_report_t const *p_adv_report = &p_ble_evt->evt.gap_evt.params.adv_report;
|
||||
uint16_t data_len = p_ble_evt->evt.gap_evt.params.adv_report.data.len;
|
||||
ble_gap_addr_t const *peer_addr = &p_ble_evt->evt.gap_evt.params.adv_report.peer_addr;
|
||||
uint64_t u64_peer_addr = 0;
|
||||
memcpy(&u64_peer_addr, peer_addr, sizeof(peer_addr->addr));
|
||||
|
||||
if (ble_advdata_uuid_find(p_adv_report->data.p_data, data_len, &filter_uuid))
|
||||
{
|
||||
mac = u64_peer_addr;
|
||||
|
||||
if (peer_addr)
|
||||
{
|
||||
char peer_addr_str[(2 + 1) * BLE_GAP_ADDR_LEN + 1] = { 0 };
|
||||
peer_addr_list[peer_addr_idx++ % COUNTOF(peer_addr_list)] = *peer_addr;
|
||||
sprintf(peer_addr_str, "%02X:%02X:%02X:%02X:%02X:%02X", peer_addr->addr[5], peer_addr->addr[4], peer_addr->addr[3], peer_addr->addr[2], peer_addr->addr[1], peer_addr->addr[0]);
|
||||
NRF_LOG_INFO("%s", peer_addr_str);
|
||||
}
|
||||
}
|
||||
else if (mac == u64_peer_addr)
|
||||
{
|
||||
on_adv_report(p_adv_report);
|
||||
}
|
||||
|
||||
sd_ble_gap_scan_start(NULL, &adv_report_buffer);
|
||||
}
|
||||
|
||||
void le_scan_get_peer_addr(ble_gap_addr_t *p_peer_addr)
|
||||
{
|
||||
for (uint32_t i = 0; i < COUNTOF(peer_addr_list); i++)
|
||||
{
|
||||
if (memcmp(peer_addr_list[i].addr, p_peer_addr->addr, BLE_GAP_ADDR_LEN) == 0)
|
||||
{
|
||||
p_peer_addr->addr_type = peer_addr_list[i].addr_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ble_gap_scan_params_t scan_params = {
|
||||
.active = 1,
|
||||
.interval = NRF_BLE_SCAN_SCAN_INTERVAL,
|
||||
.window = NRF_BLE_SCAN_SCAN_WINDOW,
|
||||
.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
|
||||
.scan_phys = BLE_GAP_PHY_1MBPS,
|
||||
.timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED,
|
||||
.channel_mask = {0, 0, 0, 0, 0},
|
||||
.report_incomplete_evts = 0,
|
||||
.extended = 0,
|
||||
};
|
||||
|
||||
void le_scan_init(void)
|
||||
{
|
||||
// TODO...
|
||||
}
|
||||
|
||||
bool is_scanning = false;
|
||||
|
||||
void le_scan_start(void)
|
||||
{
|
||||
if (is_scanning != true)
|
||||
{
|
||||
NRF_LOG_INFO("Start scanning for UUID service 0x%04X.",
|
||||
BLE_UUID_CUSTOM_SERVICE);
|
||||
is_scanning = true;
|
||||
peer_addr_idx = 0;
|
||||
memset(peer_addr_list, 0x00, sizeof(peer_addr_list));
|
||||
sd_ble_gap_scan_start(&scan_params, &adv_report_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void le_scan_stop(void)
|
||||
{
|
||||
NRF_LOG_INFO("Stop scanning.");
|
||||
sd_ble_gap_scan_stop();
|
||||
is_scanning = false;
|
||||
}
|
||||
|
||||
ble_gap_scan_params_t *le_scan_params(void)
|
||||
{
|
||||
return &scan_params;
|
||||
}
|
||||
+467
@@ -0,0 +1,467 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ble_db_discovery.h"
|
||||
#include "ble_gattc.h"
|
||||
#include "ble_srv_common.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "nrf_ble_gq.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "message_buffer.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_CNT 4
|
||||
|
||||
extern nrf_ble_gq_t *le_gap_queue(void);
|
||||
|
||||
struct le_uart_c_s
|
||||
{
|
||||
void (*evt_handler)(ble_evt_t const *p_ble_evt, void *p_context);
|
||||
uint16_t conn_handle;
|
||||
uint16_t char_handles[MAX_CHAR_CNT];
|
||||
|
||||
TimerHandle_t le_uart_c_cccd_timer;
|
||||
|
||||
MessageBufferHandle_t rx_msg;
|
||||
|
||||
SemaphoreHandle_t baud_sem;
|
||||
uint32_t baud_rate;
|
||||
};
|
||||
|
||||
#define UART_TX_HAND_IDX 0
|
||||
#define UART_RX_HAND_IDX 1
|
||||
#define UART_BAUD_HAND_IDX 2
|
||||
|
||||
typedef struct le_uart_c_s le_uart_c_t;
|
||||
|
||||
static le_uart_c_t m_le_uart_c;
|
||||
|
||||
static void on_disconnected(le_uart_c_t *p_le_uart_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
p_le_uart_c->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
for (int i = 0; i < COUNTOF(p_le_uart_c->char_handles); i++)
|
||||
{
|
||||
p_le_uart_c->char_handles[i] = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static void on_connected(le_uart_c_t *p_le_uart_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
xTimerStart(p_le_uart_c->le_uart_c_cccd_timer, 0);
|
||||
}
|
||||
|
||||
static void on_hvx(le_uart_c_t *p_le_uart_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
ble_gattc_evt_hvx_t *hvx = (void *)&p_ble_evt->evt.gattc_evt.params.hvx;
|
||||
if (p_le_uart_c->rx_msg)
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
xMessageBufferSend(p_le_uart_c->rx_msg, (void *)hvx->data, hvx->len, 0);
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
static void on_read_rsp(le_uart_c_t *p_le_uart_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
uint16_t handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle;
|
||||
ble_gattc_evt_read_rsp_t const *p_rsp = &p_ble_evt->evt.gattc_evt.params.read_rsp;
|
||||
|
||||
if (handle == p_le_uart_c->char_handles[UART_RX_HAND_IDX])
|
||||
{
|
||||
}
|
||||
else if (handle == p_le_uart_c->char_handles[UART_BAUD_HAND_IDX])
|
||||
{
|
||||
xSemaphoreGive(m_le_uart_c.baud_sem);
|
||||
m_le_uart_c.baud_rate = *(uint32_t *)p_rsp->data;
|
||||
}
|
||||
}
|
||||
|
||||
ret_code_t le_uart_ccdc_configure(uint16_t conn_handle, uint16_t char_handle, bool notification_enable)
|
||||
{
|
||||
if (conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (char_handle == BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
NRF_LOG_INFO("Configuring CCCD Handle = 0x%04X, Connection Handle = 0x%04X",
|
||||
char_handle + 1,
|
||||
conn_handle);
|
||||
|
||||
nrf_ble_gq_req_t cccd_req;
|
||||
uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INVALID;
|
||||
uint8_t cccd[BLE_CCCD_VALUE_LEN];
|
||||
|
||||
cccd[0] = LSB_16(cccd_val);
|
||||
cccd[1] = MSB_16(cccd_val);
|
||||
|
||||
memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
cccd_req.params.gattc_write.handle = char_handle + 1;
|
||||
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;
|
||||
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &cccd_req, conn_handle);
|
||||
}
|
||||
|
||||
static void le_uart_c_cccd_timer_cb(TimerHandle_t xTimer)
|
||||
{
|
||||
xTimerStop(xTimer, pdMS_TO_TICKS(0));
|
||||
|
||||
extern ret_code_t le_uart_rx_notify(bool enable);
|
||||
le_uart_rx_notify(true);
|
||||
|
||||
xMessageBufferReset(m_le_uart_c.rx_msg);
|
||||
}
|
||||
|
||||
static void le_uart_c_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
le_uart_c_t *p_le_uart_c = (le_uart_c_t *)p_context;
|
||||
|
||||
if ((p_le_uart_c == NULL) || (p_ble_evt == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
on_disconnected(p_le_uart_c, p_ble_evt);
|
||||
break;
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
on_connected(p_le_uart_c, p_ble_evt);
|
||||
break;
|
||||
case BLE_GATTC_EVT_HVX:
|
||||
/*
|
||||
Handle Value Notification or Indication event.
|
||||
Confirm indication with @ref sd_ble_gattc_hv_confirm.
|
||||
See @ref ble_gattc_evt_hvx_t. */
|
||||
on_hvx(p_le_uart_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP:
|
||||
/*
|
||||
Read Response event.
|
||||
See @ref ble_gattc_evt_read_rsp_t. */
|
||||
on_read_rsp(p_le_uart_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
/*
|
||||
Primary Service Discovery Response event.
|
||||
See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_REL_DISC_RSP:
|
||||
/*
|
||||
Relationship Discovery Response event.
|
||||
See @ref ble_gattc_evt_rel_disc_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||
/*
|
||||
Characteristic Discovery Response event.
|
||||
See @ref ble_gattc_evt_char_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP:
|
||||
/*
|
||||
Descriptor Discovery Response event.
|
||||
See @ref ble_gattc_evt_desc_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP:
|
||||
/*
|
||||
Attribute Information Response event.
|
||||
See @ref ble_gattc_evt_attr_info_disc_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
|
||||
/*
|
||||
Read By UUID Response event.
|
||||
See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_VALS_READ_RSP:
|
||||
/*
|
||||
Read multiple Response event.
|
||||
See @ref ble_gattc_evt_char_vals_read_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_WRITE_RSP:
|
||||
/*
|
||||
Write Response event.
|
||||
See @ref ble_gattc_evt_write_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
|
||||
/*
|
||||
Exchange MTU Response event.
|
||||
See @ref ble_gattc_evt_exchange_mtu_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_TIMEOUT:
|
||||
/*
|
||||
Timeout event.
|
||||
See @ref ble_gattc_evt_timeout_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE:
|
||||
/*
|
||||
Write without Response transmission complete. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void le_uart_c_on_db_disc_evt(ble_db_discovery_evt_t *p_evt)
|
||||
{
|
||||
ble_gatt_db_char_t *p_chars = p_evt->params.discovered_db.charateristics;
|
||||
|
||||
// Check if the service discovery is necessary for the link and if the event handler is present.
|
||||
if (m_le_uart_c.evt_handler == NULL || m_le_uart_c.conn_handle == p_evt->conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the uart service was discovered.
|
||||
if ((p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_UART_SERVICE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE))
|
||||
{
|
||||
m_le_uart_c.conn_handle = p_evt->conn_handle;
|
||||
|
||||
for (int i = 0; i < p_evt->params.discovered_db.char_count; i++)
|
||||
{
|
||||
for (int j = 0; j < COUNTOF(m_le_uart_c.char_handles); j++)
|
||||
{
|
||||
if (p_chars[i].characteristic.uuid.uuid == BLE_UUID_UART_CHAR(j + 1))
|
||||
{
|
||||
m_le_uart_c.char_handles[j] = p_chars[i].characteristic.handle_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void le_uart_c_error_handler(uint32_t nrf_error, void *p_contex, uint16_t conn_handle)
|
||||
{
|
||||
UNUSED_PARAMETER(conn_handle);
|
||||
__BKPT(255);
|
||||
}
|
||||
|
||||
ret_code_t le_uart_tx(uint8_t const *p_data, uint16_t len)
|
||||
{
|
||||
if (m_le_uart_c.conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
nrf_ble_gq_req_t gq_req;
|
||||
memset(&gq_req, 0, sizeof(gq_req));
|
||||
gq_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
gq_req.error_handler.cb = le_uart_c_error_handler;
|
||||
gq_req.error_handler.p_ctx = &m_le_uart_c;
|
||||
gq_req.params.gattc_write.handle = m_le_uart_c.char_handles[UART_TX_HAND_IDX];
|
||||
gq_req.params.gattc_write.p_value = p_data;
|
||||
gq_req.params.gattc_write.len = len;
|
||||
gq_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &gq_req, m_le_uart_c.conn_handle);
|
||||
}
|
||||
|
||||
ret_code_t le_uart_rx_notify(bool enable)
|
||||
{
|
||||
if (m_le_uart_c.conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (m_le_uart_c.char_handles[UART_RX_HAND_IDX] == BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ret_code_t ret = le_uart_ccdc_configure(m_le_uart_c.conn_handle, m_le_uart_c.char_handles[UART_RX_HAND_IDX], enable);
|
||||
|
||||
if (ret == NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_INFO(enable == true ? "Enable Rx notifications." : "Disable Rx notifications.");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret_code_t le_uart_rx(uint8_t *p_data, uint16_t len, uint32_t timeout)
|
||||
{
|
||||
size_t recv_size = 0;
|
||||
if (timeout)
|
||||
{
|
||||
recv_size = xMessageBufferReceive(m_le_uart_c.rx_msg, p_data, len, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
recv_size = xMessageBufferReceive(m_le_uart_c.rx_msg, p_data, len, 0);
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
if (recv_size)
|
||||
{
|
||||
return recv_size;
|
||||
}
|
||||
return NRF_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
ret_code_t le_uart_baudrate_get(uint32_t *baudrate)
|
||||
{
|
||||
ret_code_t ret;
|
||||
|
||||
if (m_le_uart_c.conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
nrf_ble_gq_req_t gq_req;
|
||||
memset(&gq_req, 0, sizeof(gq_req));
|
||||
gq_req.type = NRF_BLE_GQ_REQ_GATTC_READ;
|
||||
gq_req.error_handler.cb = le_uart_c_error_handler;
|
||||
gq_req.error_handler.p_ctx = &m_le_uart_c;
|
||||
gq_req.params.gattc_read.handle = m_le_uart_c.char_handles[UART_BAUD_HAND_IDX];
|
||||
|
||||
ret = nrf_ble_gq_item_add(le_gap_queue(), &gq_req, m_le_uart_c.conn_handle);
|
||||
|
||||
if (ret == NRF_SUCCESS)
|
||||
{
|
||||
if (xSemaphoreTake(m_le_uart_c.baud_sem, pdMS_TO_TICKS(100)) == pdFALSE)
|
||||
{
|
||||
return NRF_ERROR_TIMEOUT;
|
||||
}
|
||||
*baudrate = m_le_uart_c.baud_rate;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret_code_t le_uart_baudrate_set(uint32_t baudrate)
|
||||
{
|
||||
if (m_le_uart_c.conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
nrf_ble_gq_req_t gq_req;
|
||||
memset(&gq_req, 0, sizeof(gq_req));
|
||||
gq_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
gq_req.error_handler.cb = le_uart_c_error_handler;
|
||||
gq_req.error_handler.p_ctx = &m_le_uart_c;
|
||||
gq_req.params.gattc_write.handle = m_le_uart_c.char_handles[UART_BAUD_HAND_IDX];
|
||||
gq_req.params.gattc_write.p_value = (void *)&baudrate;
|
||||
gq_req.params.gattc_write.len = sizeof(baudrate);
|
||||
gq_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ;
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &gq_req, m_le_uart_c.conn_handle);
|
||||
}
|
||||
|
||||
static void ble_uart_echo(void *p_arg)
|
||||
{
|
||||
void le_scan_start(void);
|
||||
le_scan_start();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
|
||||
void le_scan_stop(void);
|
||||
le_scan_stop();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
ble_gap_addr_t peer_addr;
|
||||
peer_addr.addr_id_peer = 0;
|
||||
peer_addr.addr_type = BLE_GAP_ADDR_TYPE_ANONYMOUS;
|
||||
peer_addr.addr[0] = 0xDA;
|
||||
peer_addr.addr[1] = 0x71;
|
||||
peer_addr.addr[2] = 0x1F;
|
||||
peer_addr.addr[3] = 0x1F;
|
||||
peer_addr.addr[4] = 0x05;
|
||||
peer_addr.addr[5] = 0xDC;
|
||||
|
||||
extern void le_scan_get_peer_addr(ble_gap_addr_t * p_peer_addr);
|
||||
le_scan_get_peer_addr(&peer_addr);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
|
||||
extern void le_gap_connet(ble_gap_addr_t * p_peer_addr);
|
||||
le_gap_connet(&peer_addr);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
uint32_t get_baud = 1000000;
|
||||
uint32_t set_baud = 115200;
|
||||
extern ret_code_t le_uart_baudrate_get(uint32_t * baudrate);
|
||||
le_uart_baudrate_get(&get_baud);
|
||||
NRF_LOG_INFO("Get Baud rate: %d", get_baud);
|
||||
|
||||
extern ret_code_t le_uart_baudrate_set(uint32_t baudrate);
|
||||
le_uart_baudrate_set(set_baud);
|
||||
NRF_LOG_INFO("Set Baud rate: %d", set_baud);
|
||||
|
||||
le_uart_baudrate_get(&get_baud);
|
||||
NRF_LOG_INFO("Get Baud rate: %d", get_baud);
|
||||
|
||||
extern ret_code_t le_uart_tx(uint8_t const *p_data, uint16_t len);
|
||||
uint8_t str[] = "ABCDEF";
|
||||
le_uart_tx(str, strlen(str));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t recv[256];
|
||||
uint32_t size;
|
||||
size = le_uart_rx(recv, sizeof(recv), portMAX_DELAY);
|
||||
le_uart_tx(recv, size);
|
||||
}
|
||||
}
|
||||
|
||||
void le_uart_c_init(void)
|
||||
{
|
||||
m_le_uart_c.rx_msg = xMessageBufferCreate(4096);
|
||||
m_le_uart_c.baud_sem = xSemaphoreCreateBinary();
|
||||
m_le_uart_c.evt_handler = le_uart_c_evt_handler;
|
||||
m_le_uart_c.conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
for (int i = 0; i < COUNTOF(m_le_uart_c.char_handles); i++)
|
||||
{
|
||||
m_le_uart_c.char_handles[i] = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
ret_code_t err_code;
|
||||
uint8_t uuid_type;
|
||||
ble_uuid_t uuid = {
|
||||
.type = BLE_UUID_TYPE_BLE,
|
||||
.uuid = BLE_UUID_UART_SERVICE,
|
||||
};
|
||||
err_code = ble_db_discovery_evt_register(&uuid);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
NRF_SDH_BLE_OBSERVER(m_uart_c_observer, 1, le_uart_c_evt_handler, &m_le_uart_c);
|
||||
|
||||
m_le_uart_c.le_uart_c_cccd_timer = xTimerCreate("Timer", pdMS_TO_TICKS(1000), pdTRUE, (void *)1, le_uart_c_cccd_timer_cb);
|
||||
|
||||
#if 0
|
||||
xTaskCreate(ble_uart_echo, "ble uart echo", 2048, NULL, 3, NULL);
|
||||
#endif
|
||||
}
|
||||
+16
-10
@@ -40,8 +40,11 @@ static void le_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
ret_code_t err_code;
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_ADV_REPORT:
|
||||
break;
|
||||
case BLE_GAP_EVT_ADV_REPORT: {
|
||||
extern void le_scan_handler(ble_evt_t const *p_ble_evt, void *p_context);
|
||||
le_scan_handler(p_ble_evt, p_context);
|
||||
}
|
||||
break;
|
||||
case BLE_GAP_EVT_PHY_UPDATE:
|
||||
NRF_LOG_INFO("PHY update procedure is complete.");
|
||||
break;
|
||||
@@ -50,7 +53,6 @@ static void le_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
break;
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
NRF_LOG_INFO("Connected to peer.");
|
||||
le_scan_stop();
|
||||
le_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle);
|
||||
le_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle);
|
||||
le_db_discovery_start(p_ble_evt->evt.gap_evt.conn_handle);
|
||||
@@ -62,7 +64,8 @@ static void le_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
le_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle);
|
||||
break;
|
||||
case BLE_GATTS_EVT_SYS_ATTR_MISSING: {
|
||||
ret_code_t err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0);
|
||||
ret_code_t err_code = sd_ble_gatts_sys_attr_set(
|
||||
p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
break;
|
||||
@@ -104,17 +107,20 @@ static void initialize(void *p_context)
|
||||
extern void uart_drv_init(void);
|
||||
uart_drv_init();
|
||||
|
||||
extern void sram_drv_init(void);
|
||||
sram_drv_init();
|
||||
|
||||
extern void mem_board_init(void);
|
||||
mem_board_init();
|
||||
|
||||
extern void le_db_discovery_init(void);
|
||||
le_db_discovery_init();
|
||||
|
||||
extern void le_dis_c_init(void);
|
||||
le_dis_c_init();
|
||||
|
||||
extern void le_eis_c_init(void);
|
||||
le_eis_c_init();
|
||||
extern void le_gatt_c_init(void);
|
||||
le_gatt_c_init();
|
||||
|
||||
extern void le_uart_c_init(void);
|
||||
le_uart_c_init();
|
||||
|
||||
extern void le_gap_init(void);
|
||||
le_gap_init();
|
||||
@@ -131,7 +137,7 @@ static void initialize(void *p_context)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
NRF_LOG_INIT(NULL, 0);
|
||||
NRF_LOG_INIT(xTaskGetTickCount, configTICK_RATE_HZ);
|
||||
NRF_LOG_DEFAULT_BACKENDS_INIT();
|
||||
NRF_LOG_INFO("%s Build: %s %s", LE_DEVICE_NAME, __TIME__, __DATE__);
|
||||
|
||||
+283
@@ -0,0 +1,283 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_gpiote.h"
|
||||
#include "nrf_spim.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "message_buffer.h"
|
||||
#include "semphr.h"
|
||||
#include "stream_buffer.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MEM_SEL_PIN NRF_GPIO_PIN_MAP(1, 9)
|
||||
#define MEM_BZY_PIN NRF_GPIO_PIN_MAP(0, 8)
|
||||
#define MEM_REQ_PIN NRF_GPIO_PIN_MAP(0, 6)
|
||||
|
||||
#define RAM_SEL_PIN NRF_GPIO_PIN_MAP(0, 5)
|
||||
|
||||
#define MEM_TEST_01_PIN NRF_GPIO_PIN_MAP(0, 26)
|
||||
#define MEM_TEST_02_PIN NRF_GPIO_PIN_MAP(0, 17)
|
||||
#define MEM_TEST_03_PIN NRF_GPIO_PIN_MAP(0, 21)
|
||||
#define MEM_TEST_04_PIN NRF_GPIO_PIN_MAP(0, 19)
|
||||
#define MEM_TEST_05_PIN NRF_GPIO_PIN_MAP(0, 22)
|
||||
|
||||
#define MEM_SEL_GPIOTE_ID 0
|
||||
#define MEM_REQ_GPIOTE_ID 1
|
||||
|
||||
#define MEM_DATA_UNIT 40
|
||||
|
||||
#define MEM_DUMP 0
|
||||
|
||||
static int ram_sel = 0;
|
||||
|
||||
static SemaphoreHandle_t mem_sel_semphr = NULL;
|
||||
static TaskHandle_t mem_drv_task_handle = NULL;
|
||||
static StreamBufferHandle_t mem_drv_stream = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t val;
|
||||
struct
|
||||
{
|
||||
uint16_t len;
|
||||
uint16_t marker;
|
||||
} __PACKED;
|
||||
} header[3];
|
||||
} green_frame;
|
||||
uint8_t red_frame[2048];
|
||||
} mem_data_t;
|
||||
mem_data_t mem_data;
|
||||
uint32_t mem_notify_cnt = 0;
|
||||
uint32_t mem_req;
|
||||
uint32_t mem_sel;
|
||||
|
||||
void mem_ram_select(int select)
|
||||
{
|
||||
ram_sel = select;
|
||||
switch (ram_sel)
|
||||
{
|
||||
case 0:
|
||||
nrf_gpio_pin_clear(RAM_SEL_PIN);
|
||||
break;
|
||||
case 1:
|
||||
nrf_gpio_pin_set(RAM_SEL_PIN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
NRF_LOG_INFO("Select SRAM: %d", ram_sel);
|
||||
}
|
||||
|
||||
extern int sram_drv_write(uint32_t addr, void *p_dest, uint32_t len);
|
||||
extern int sram_drv_read(uint32_t addr, void *p_dest, uint32_t len);
|
||||
|
||||
static bool chk_sram_swtich_evt(uint32_t *new_ram_sel)
|
||||
{
|
||||
/************************************************
|
||||
* When the mem_sel is in a low-level state,
|
||||
* the state of mem_req is considered valid.
|
||||
************************************************/
|
||||
while (mem_sel == false)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
|
||||
/* sync mem_req status */
|
||||
mem_req = nrf_gpio_pin_read(MEM_REQ_PIN);
|
||||
|
||||
if (mem_req != ram_sel)
|
||||
{
|
||||
*new_ram_sel = mem_req;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static void mem_drv_task(void *p_arg)
|
||||
{
|
||||
extern void sram_drv_init(void);
|
||||
sram_drv_init();
|
||||
|
||||
extern void sram_drv_reset(void);
|
||||
mem_ram_select(0);
|
||||
sram_drv_reset();
|
||||
mem_ram_select(1);
|
||||
sram_drv_reset();
|
||||
mem_ram_select(0);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint32_t new_ram_sel;
|
||||
|
||||
xSemaphoreTake(mem_sel_semphr, portMAX_DELAY);
|
||||
|
||||
if (chk_sram_swtich_evt(&new_ram_sel) == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
|
||||
uint32_t green_frame_size = sizeof(mem_data.green_frame);
|
||||
uint32_t red_frame_size = 0;
|
||||
uint32_t total_size = 0;
|
||||
|
||||
/* read red frame data from streambuffer */
|
||||
taskENTER_CRITICAL();
|
||||
red_frame_size = xStreamBufferReceive(mem_drv_stream, mem_data.red_frame, sizeof(mem_data.red_frame), 0);
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* write green & red frame data to sram */
|
||||
total_size = green_frame_size + red_frame_size;
|
||||
mem_data.green_frame.header[0].len = __REVSH(total_size);
|
||||
mem_data.green_frame.header[0].marker = __REVSH(0xA55A);
|
||||
mem_data.green_frame.header[1].val = mem_data.green_frame.header[0].val;
|
||||
mem_data.green_frame.header[2].val = mem_data.green_frame.header[0].val;
|
||||
sram_drv_write(0x0000, &mem_data, total_size);
|
||||
|
||||
/* switch sram */
|
||||
mem_ram_select(new_ram_sel);
|
||||
|
||||
#if MEM_DUMP
|
||||
for (uint32_t i = 0; i < total_size / 32; i++)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)&mem_data;
|
||||
NRF_LOG_HEXDUMP_INFO(&p[i * 32], 32);
|
||||
}
|
||||
if (total_size % 32)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)&mem_data;
|
||||
NRF_LOG_HEXDUMP_INFO(&p[(total_size / 32) * 32], total_size % 32);
|
||||
}
|
||||
#endif
|
||||
NRF_LOG_INFO("Write: %4d bytes, and switch sram done!!!", total_size);
|
||||
}
|
||||
}
|
||||
|
||||
void mem_board_reset(void)
|
||||
{
|
||||
mem_notify_cnt = 0;
|
||||
xStreamBufferReset(mem_drv_stream);
|
||||
}
|
||||
|
||||
void mem_notify_cb(uint8_t *p, uint32_t len)
|
||||
{
|
||||
/* write red frame data to streambuffer */
|
||||
|
||||
static struct
|
||||
{
|
||||
uint8_t prefix;
|
||||
uint8_t cnt;
|
||||
uint8_t len;
|
||||
uint8_t content[64];
|
||||
} swap_buf;
|
||||
|
||||
swap_buf.prefix = 0xFF;
|
||||
swap_buf.cnt = mem_notify_cnt++;
|
||||
swap_buf.len = len;
|
||||
memcpy(swap_buf.content, p, len);
|
||||
|
||||
swap_buf.content[len + 0] = 0;
|
||||
swap_buf.content[len + 1] = 0;
|
||||
swap_buf.content[len + 2] = 0;
|
||||
swap_buf.content[len + 3] = 0;
|
||||
swap_buf.content[len + 4] = 0;
|
||||
|
||||
uint32_t sum = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
sum += p[i];
|
||||
}
|
||||
sum += swap_buf.prefix;
|
||||
sum += swap_buf.cnt;
|
||||
sum += swap_buf.len;
|
||||
swap_buf.content[len + 5] = sum & 0xFF;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
xStreamBufferSend(mem_drv_stream, &swap_buf, 3 + len + 6, 0);
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void mem_board_init(void)
|
||||
{
|
||||
// Config RAM test pin
|
||||
nrf_gpio_cfg_input(MEM_TEST_01_PIN, NRF_GPIO_PIN_PULLUP);
|
||||
nrf_gpio_cfg_input(MEM_TEST_02_PIN, NRF_GPIO_PIN_PULLUP);
|
||||
nrf_gpio_cfg_input(MEM_TEST_03_PIN, NRF_GPIO_PIN_PULLUP);
|
||||
nrf_gpio_cfg_input(MEM_TEST_04_PIN, NRF_GPIO_PIN_PULLUP);
|
||||
nrf_gpio_cfg_input(MEM_TEST_05_PIN, NRF_GPIO_PIN_PULLUP);
|
||||
|
||||
// Config RAM select pin
|
||||
nrf_gpio_cfg_output(RAM_SEL_PIN);
|
||||
nrf_gpio_pin_clear(RAM_SEL_PIN);
|
||||
|
||||
// Config PI Ctrl pin
|
||||
nrf_gpio_cfg_input(MEM_SEL_PIN, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_cfg_input(MEM_REQ_PIN, NRF_GPIO_PIN_NOPULL);
|
||||
|
||||
nrf_gpiote_event_configure(MEM_SEL_GPIOTE_ID, MEM_SEL_PIN, NRF_GPIOTE_POLARITY_TOGGLE);
|
||||
nrf_gpiote_event_enable(MEM_SEL_GPIOTE_ID);
|
||||
nrf_gpiote_int_enable(0x01 << MEM_SEL_GPIOTE_ID);
|
||||
|
||||
nrf_gpiote_event_configure(MEM_REQ_GPIOTE_ID, MEM_REQ_PIN, NRF_GPIOTE_POLARITY_TOGGLE);
|
||||
nrf_gpiote_event_enable(MEM_REQ_GPIOTE_ID);
|
||||
nrf_gpiote_int_enable(0x01 << MEM_REQ_GPIOTE_ID);
|
||||
|
||||
// Create Semphr & Task
|
||||
mem_sel_semphr = xSemaphoreCreateBinary();
|
||||
mem_drv_stream = xStreamBufferCreate(4096, 1);
|
||||
xTaskCreate(mem_drv_task, "mem_drv", 256, NULL, 5, NULL);
|
||||
|
||||
sd_nvic_SetPriority(GPIOTE_IRQn, _PRIO_APP_MID);
|
||||
sd_nvic_EnableIRQ(GPIOTE_IRQn);
|
||||
}
|
||||
|
||||
static void mem_sel_isr(void)
|
||||
{
|
||||
mem_sel = nrf_gpio_pin_read(MEM_SEL_PIN);
|
||||
if (mem_sel == 0)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
xSemaphoreGiveFromISR(mem_sel_semphr, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
|
||||
static void mem_req_isr(void)
|
||||
{
|
||||
mem_req = nrf_gpio_pin_read(MEM_REQ_PIN);
|
||||
}
|
||||
|
||||
void GPIOTE_IRQHandler(void)
|
||||
{
|
||||
if (NRF_GPIOTE->EVENTS_IN[MEM_SEL_GPIOTE_ID])
|
||||
{
|
||||
NRF_GPIOTE->EVENTS_IN[MEM_SEL_GPIOTE_ID] = 0;
|
||||
mem_sel_isr();
|
||||
return;
|
||||
}
|
||||
if (NRF_GPIOTE->EVENTS_IN[MEM_REQ_GPIOTE_ID])
|
||||
{
|
||||
NRF_GPIOTE->EVENTS_IN[MEM_REQ_GPIOTE_ID] = 0;
|
||||
mem_req_isr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
+62
-33
@@ -4,6 +4,7 @@
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include "app_config.h"
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_spim.h"
|
||||
@@ -29,10 +30,12 @@ extern "C"
|
||||
#define READ_STATUS_CMD (0b00000101)
|
||||
#define WRITE_STATUS_CMD (0b00000001)
|
||||
|
||||
#define BYTE_MODE (0b00)
|
||||
#define PAGE_MODE (0b10)
|
||||
#define SEQ_MODE (0b01)
|
||||
#define RESVD_MODE (0b11)
|
||||
#define BYTE_MODE (0b00000010)
|
||||
#define PAGE_MODE (0b10000010)
|
||||
#define SEQ_MODE (0b01000010)
|
||||
#define RESVD_MODE (0b11000010)
|
||||
|
||||
#define HOLD_DISABLE (0b00000001)
|
||||
|
||||
#if (SRAM_DEVICE == SRAM_23K640)
|
||||
#define SRAM_SIZE (64 * 1024 / 8)
|
||||
@@ -43,20 +46,14 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#define SRAM_SPIM (NRF_SPIM3)
|
||||
#define CS0_PIN NRF_GPIO_PIN_MAP(1, 11)
|
||||
#define CS1_PIN NRF_GPIO_PIN_MAP(1, 12)
|
||||
#define SCLK_PIN NRF_GPIO_PIN_MAP(1, 13)
|
||||
#define MOSI_PIN NRF_GPIO_PIN_MAP(1, 14)
|
||||
#define MISO_PIN NRF_GPIO_PIN_MAP(1, 15)
|
||||
#define CS_PIN NRF_GPIO_PIN_MAP(0, 7)
|
||||
#define SCLK_PIN NRF_GPIO_PIN_MAP(0, 12)
|
||||
#define MOSI_PIN NRF_GPIO_PIN_MAP(0, 14)
|
||||
#define MISO_PIN NRF_GPIO_PIN_MAP(0, 11)
|
||||
|
||||
static SemaphoreHandle_t txrx_end_sem;
|
||||
static SemaphoreHandle_t sram_mutex;
|
||||
|
||||
const uint8_t cs_bank[SRAM_BANK_NUM] = {
|
||||
CS0_PIN,
|
||||
CS1_PIN
|
||||
};
|
||||
|
||||
static void write_bytes(void *p, uint32_t len)
|
||||
{
|
||||
nrf_spim_tx_buffer_set(SRAM_SPIM, p, len);
|
||||
@@ -73,6 +70,16 @@ static void read_bytes(void *p, uint32_t len)
|
||||
xSemaphoreTake(txrx_end_sem, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void read_write_bytes(void *tx, uint32_t tx_len, void *rx, uint32_t rx_len)
|
||||
{
|
||||
static uint8_t recv[256];
|
||||
nrf_spim_tx_buffer_set(SRAM_SPIM, tx, tx_len);
|
||||
nrf_spim_rx_buffer_set(SRAM_SPIM, recv, tx_len + rx_len);
|
||||
nrf_spim_task_trigger(SRAM_SPIM, NRF_SPIM_TASK_START);
|
||||
xSemaphoreTake(txrx_end_sem, portMAX_DELAY);
|
||||
memcpy(rx, &recv[tx_len], rx_len);
|
||||
}
|
||||
|
||||
static void write_status(uint8_t mode)
|
||||
{
|
||||
uint8_t buf[] = {
|
||||
@@ -80,6 +87,14 @@ static void write_status(uint8_t mode)
|
||||
};
|
||||
write_bytes(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static void read_status(uint8_t *mode)
|
||||
{
|
||||
uint8_t send[] = {
|
||||
READ_STATUS_CMD
|
||||
};
|
||||
read_write_bytes(send, sizeof(send), mode, sizeof(*mode));
|
||||
}
|
||||
static void write_inst_addr(uint32_t inst, uint32_t addr)
|
||||
{
|
||||
uint8_t buf[] = {
|
||||
@@ -90,37 +105,57 @@ static void write_inst_addr(uint32_t inst, uint32_t addr)
|
||||
write_bytes(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void sram_drv_write_status(uint32_t bank, uint8_t mode)
|
||||
void sram_drv_write_status(uint8_t mode)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
nrf_gpio_pin_clear(cs_bank[bank & 0x01]);
|
||||
write_status(mode);
|
||||
nrf_gpio_pin_set(cs_bank[bank & 0x01]);
|
||||
nrf_gpio_pin_clear(CS_PIN);
|
||||
write_status(mode | HOLD_DISABLE);
|
||||
nrf_gpio_pin_set(CS_PIN);
|
||||
xSemaphoreGive(sram_mutex);
|
||||
}
|
||||
|
||||
int sram_drv_write(uint32_t bank, uint32_t addr, void *p_dest, uint32_t len)
|
||||
void sram_drv_read_status(uint8_t *mode)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
nrf_gpio_pin_clear(cs_bank[bank & 0x01]);
|
||||
nrf_gpio_pin_clear(CS_PIN);
|
||||
read_status(mode);
|
||||
nrf_gpio_pin_set(CS_PIN);
|
||||
xSemaphoreGive(sram_mutex);
|
||||
}
|
||||
int sram_drv_write(uint32_t addr, void *p_dest, uint32_t len)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
nrf_gpio_pin_clear(CS_PIN);
|
||||
write_inst_addr(WRITE_CMD, addr);
|
||||
write_bytes(p_dest, len);
|
||||
nrf_gpio_pin_set(cs_bank[bank & 0x01]);
|
||||
nrf_gpio_pin_set(CS_PIN);
|
||||
xSemaphoreGive(sram_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sram_drv_read(uint32_t bank, uint32_t addr, void *p_dest, uint32_t len)
|
||||
int sram_drv_read(uint32_t addr, void *p_dest, uint32_t len)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
nrf_gpio_pin_clear(cs_bank[bank & 0x01]);
|
||||
nrf_gpio_pin_clear(CS_PIN);
|
||||
write_inst_addr(READ_CMD, addr);
|
||||
read_bytes(p_dest, len);
|
||||
nrf_gpio_pin_set(cs_bank[bank & 0x01]);
|
||||
nrf_gpio_pin_set(CS_PIN);
|
||||
xSemaphoreGive(sram_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t dummy[32] = { 0 };
|
||||
void sram_drv_reset(void)
|
||||
{
|
||||
sram_drv_write_status(SEQ_MODE);
|
||||
memset(dummy, 0x00, COUNTOF(dummy));
|
||||
for (int i = 0; i < SRAM_SIZE / COUNTOF(dummy); i++)
|
||||
{
|
||||
uint32_t addr = i * COUNTOF(dummy);
|
||||
sram_drv_write(addr, dummy, sizeof(dummy));
|
||||
}
|
||||
}
|
||||
|
||||
void sram_drv_init(void)
|
||||
{
|
||||
txrx_end_sem = xSemaphoreCreateBinary();
|
||||
@@ -133,12 +168,9 @@ void sram_drv_init(void)
|
||||
// Config SPI clk pin
|
||||
nrf_gpio_cfg_output(SCLK_PIN);
|
||||
nrf_gpio_pin_clear(SCLK_PIN);
|
||||
// Config SPI cs0 pin
|
||||
nrf_gpio_cfg_output(CS0_PIN);
|
||||
nrf_gpio_pin_set(CS0_PIN);
|
||||
// Config SPI cs1 pin
|
||||
nrf_gpio_cfg_output(CS1_PIN);
|
||||
nrf_gpio_pin_set(CS1_PIN);
|
||||
// Config SPI cs pin
|
||||
nrf_gpio_cfg_output(CS_PIN);
|
||||
nrf_gpio_pin_set(CS_PIN);
|
||||
|
||||
// Config SPI module
|
||||
nrf_spim_configure(SRAM_SPIM, NRF_SPIM_MODE_0, NRF_SPIM_BIT_ORDER_MSB_FIRST);
|
||||
@@ -153,9 +185,6 @@ void sram_drv_init(void)
|
||||
sd_nvic_SetPriority(SPIM3_IRQn, _PRIO_APP_MID);
|
||||
sd_nvic_EnableIRQ(SPIM3_IRQn);
|
||||
nrf_spim_int_enable(SRAM_SPIM, NRF_SPIM_INT_END_MASK);
|
||||
|
||||
sram_drv_write_status(0, SEQ_MODE);
|
||||
sram_drv_write_status(1, SEQ_MODE);
|
||||
}
|
||||
|
||||
void SPIM3_IRQHandler(void)
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file syscalls.c
|
||||
* @author Auto-generated by STM32CubeIDE
|
||||
* @brief STM32CubeIDE Minimal System calls file
|
||||
*
|
||||
* For more information about which c-functions
|
||||
* need which of these lowlevel functions
|
||||
* please consult the Newlib libc-manual
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2022 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes */
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
|
||||
/* Variables */
|
||||
extern int __io_putchar(int ch) __attribute__((weak));
|
||||
extern int __io_getchar(void) __attribute__((weak));
|
||||
|
||||
|
||||
char *__env[1] = { 0 };
|
||||
char **environ = __env;
|
||||
|
||||
|
||||
/* Functions */
|
||||
void initialise_monitor_handles()
|
||||
{
|
||||
}
|
||||
|
||||
int _getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _exit (int status)
|
||||
{
|
||||
_kill(status, -1);
|
||||
while (1) {} /* Make sure we hang here */
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int file, char *ptr, int len)
|
||||
{
|
||||
int DataIdx;
|
||||
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
*ptr++ = __io_getchar();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int file, char *ptr, int len)
|
||||
{
|
||||
int DataIdx;
|
||||
|
||||
for (DataIdx = 0; DataIdx < len; DataIdx++)
|
||||
{
|
||||
__io_putchar(*ptr++);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int _close(int file)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int file)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _open(char *path, int flags, ...)
|
||||
{
|
||||
/* Pretend like we always fail */
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _wait(int *status)
|
||||
{
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink(char *name)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _times(struct tms *buf)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat(char *file, struct stat *st)
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _link(char *old, char *new)
|
||||
{
|
||||
errno = EMLINK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fork(void)
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _execve(char *name, char **argv, char **env)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
@@ -21,8 +21,8 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#define HOST_UART (NRF_UARTE0)
|
||||
#define HOST_UART_DRV_TX_PIN 6
|
||||
#define HOST_UART_DRV_RX_PIN 8
|
||||
#define HOST_UART_DRV_TX_PIN NRF_GPIO_PIN_MAP(0, 4)
|
||||
#define HOST_UART_DRV_RX_PIN NRF_GPIO_PIN_MAP(0, 27)
|
||||
|
||||
static SemaphoreHandle_t uart_drv_tx_sem;
|
||||
static SemaphoreHandle_t uart_drv_rx_sem;
|
||||
@@ -76,7 +76,7 @@ void uart_drv_init(void)
|
||||
nrf_gpio_cfg_output(HOST_UART_DRV_TX_PIN);
|
||||
nrf_gpio_cfg_input(HOST_UART_DRV_RX_PIN, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_uarte_configure(HOST_UART, NRF_UARTE_PARITY_EXCLUDED, NRF_UARTE_HWFC_DISABLED);
|
||||
nrf_uarte_baudrate_set(HOST_UART, NRF_UARTE_BAUDRATE_57600);
|
||||
nrf_uarte_baudrate_set(HOST_UART, NRF_UARTE_BAUDRATE_115200);
|
||||
nrf_uarte_txrx_pins_set(HOST_UART, HOST_UART_DRV_TX_PIN, HOST_UART_DRV_RX_PIN);
|
||||
nrf_uarte_hwfc_pins_disconnect(HOST_UART);
|
||||
nrf_uarte_enable(HOST_UART);
|
||||
@@ -25,6 +25,7 @@
|
||||
<ProjectFile>bmd380_central.vcxproj</ProjectFile>
|
||||
<RemoteBuildEnvironment>
|
||||
<Records />
|
||||
<EnvironmentSetupFiles />
|
||||
</RemoteBuildEnvironment>
|
||||
<ParallelJobCount>1</ParallelJobCount>
|
||||
<SuppressDirectoryChangeMessages>true</SuppressDirectoryChangeMessages>
|
||||
@@ -94,15 +95,17 @@
|
||||
<EnableAsyncExecutionMode>false</EnableAsyncExecutionMode>
|
||||
<AsyncModeSupportsBreakpoints>true</AsyncModeSupportsBreakpoints>
|
||||
<TemporaryBreakConsolidationTimeout>0</TemporaryBreakConsolidationTimeout>
|
||||
<BacktraceFrameLimit>0</BacktraceFrameLimit>
|
||||
<EnableNonStopMode>false</EnableNonStopMode>
|
||||
<MaxBreakpointLimit>0</MaxBreakpointLimit>
|
||||
<EnableVerboseMode>true</EnableVerboseMode>
|
||||
<EnablePrettyPrinters>false</EnablePrettyPrinters>
|
||||
<EnableAbsolutePathReporting>true</EnableAbsolutePathReporting>
|
||||
</AdditionalGDBSettings>
|
||||
<DebugMethod>
|
||||
<ID>jlink-jtag</ID>
|
||||
<InterfaceID>com.sysprogs.debug.jlink.jlinksw</InterfaceID>
|
||||
<InterfaceSerialNumber>000682409936</InterfaceSerialNumber>
|
||||
<InterfaceSerialNumber>000601012352</InterfaceSerialNumber>
|
||||
<Configuration xsi:type="com.visualgdb.edp.segger.settings">
|
||||
<CommandLine>-select USB -device $$SYS:MCU_ID$$ -speed auto -if SWD</CommandLine>
|
||||
<ProgramMode>Enabled</ProgramMode>
|
||||
@@ -129,7 +132,7 @@
|
||||
<EndOfStackSymbol>_estack</EndOfStackSymbol>
|
||||
<TimestampProviderTicksPerSecond>0</TimestampProviderTicksPerSecond>
|
||||
<KeepConsoleAfterExit>false</KeepConsoleAfterExit>
|
||||
<UnusedStackFillPattern xsi:nil="true" />
|
||||
<UnusedStackFillPattern>2779096485</UnusedStackFillPattern>
|
||||
<CheckInterfaceDrivers>true</CheckInterfaceDrivers>
|
||||
</Debug>
|
||||
</VisualGDBProjectSettings2>
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../bmd380_sdk"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"ble_db_discovery.h": "c",
|
||||
"ble_dis_c.h": "c",
|
||||
"sdk_config.h": "c"
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-4
@@ -32,13 +32,15 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
|
||||
<GNUConfigurationType>Debug</GNUConfigurationType>
|
||||
<ToolchainID>com.visualgdb.arm-eabi</ToolchainID>
|
||||
<ToolchainVersion>10.3.1/10.2.90/r1</ToolchainVersion>
|
||||
<ToolchainVersion>14.2.1/15.2/r2</ToolchainVersion>
|
||||
<MCUPropertyListFile>$(ProjectDir)nrf5x.props</MCUPropertyListFile>
|
||||
<UseCCache>true</UseCCache>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
|
||||
<ToolchainID>com.visualgdb.arm-eabi</ToolchainID>
|
||||
<ToolchainVersion>10.3.1/10.2.90/r1</ToolchainVersion>
|
||||
<ToolchainVersion>14.2.1/15.2/r2</ToolchainVersion>
|
||||
<MCUPropertyListFile>$(ProjectDir)nrf5x.props</MCUPropertyListFile>
|
||||
<UseCCache>true</UseCCache>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
|
||||
<ClCompile>
|
||||
@@ -49,13 +51,16 @@
|
||||
<SupportRTTI>false</SupportRTTI>
|
||||
<AdditionalOptions />
|
||||
<CPPLanguageStandard />
|
||||
<Optimization>O0</Optimization>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LinkerScript>nRF52811_XXAA_s140.lds</LinkerScript>
|
||||
<LibrarySearchDirectories>%(Link.LibrarySearchDirectories)</LibrarySearchDirectories>
|
||||
<AdditionalLibraryNames>%(Link.AdditionalLibraryNames)</AdditionalLibraryNames>
|
||||
<AdditionalLinkerInputs>%(Link.AdditionalLinkerInputs)</AdditionalLinkerInputs>
|
||||
<AdditionalOptions />
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
|
||||
@@ -65,6 +70,7 @@
|
||||
<CLanguageStandard>GNU99</CLanguageStandard>
|
||||
<SupportExceptions>false</SupportExceptions>
|
||||
<SupportRTTI>false</SupportRTTI>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<LinkerScript>nRF52811_XXAA_s140.lds</LinkerScript>
|
||||
@@ -77,7 +83,11 @@
|
||||
</ImportGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="host_tasks.c" />
|
||||
<ClCompile Include="le_gatt_c.c" />
|
||||
<ClCompile Include="le_uart_c.c" />
|
||||
<ClCompile Include="mem_drv.c" />
|
||||
<ClCompile Include="sram_drv.c" />
|
||||
<ClCompile Include="syscalls.c" />
|
||||
<ClCompile Include="uart_drv.c" />
|
||||
<None Include="nrf5x.props" />
|
||||
<ClCompile Include="$(BSP_ROOT)\nRF5x\modules\nrfx\mdk\system_nrf52840.c" />
|
||||
@@ -380,7 +390,6 @@
|
||||
<ClCompile Include="..\bmd380_sdk\components\libraries\queue\nrf_queue.c" />
|
||||
<ClCompile Include="le_db_discovery.c" />
|
||||
<ClCompile Include="le_dis_c.c" />
|
||||
<ClCompile Include="le_eis_c.c" />
|
||||
<ClCompile Include="le_gap.c" />
|
||||
<ClCompile Include="le_gatt.c" />
|
||||
<ClCompile Include="le_gap_queue.c" />
|
||||
|
||||
@@ -1667,9 +1667,6 @@
|
||||
<ClCompile Include="le_dis_c.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="le_eis_c.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="uart_drv.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
@@ -1679,6 +1676,18 @@
|
||||
<ClCompile Include="sram_drv.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="le_gatt_c.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mem_drv.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="syscalls.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="le_uart_c.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\bmd380_sdk\components\ble\ble_services\ble_dis_c\ble_dis_c.h">
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# Call Cmake from the 'build' subfolder with the command below.
|
||||
# For using Make:
|
||||
# cmake -DCMAKE_MAKE_PROGRAM=make.exe -DCMAKE_TOOLCHAIN_FILE="arm-none-eabi-gcc.cmake" -G "Unix Makefiles" ..
|
||||
# followed by
|
||||
# 'make' or 'cmake --build .' to build it
|
||||
#
|
||||
# For using Ninja:
|
||||
# cmake -DCMAKE_MAKE_PROGRAM=ninja.exe -DCMAKE_TOOLCHAIN_FILE="arm-none-eabi-gcc.cmake" -G "Ninja" ..
|
||||
# followed by
|
||||
# 'ninja' or 'cmake --build .' to build it
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
if(CMAKE_HOST_WIN32)
|
||||
set(EXECUTESUFFIX ".exe")
|
||||
set(ARM_TOOLCHAIN_DIR "C:/SysGCC/arm-eabi/bin")
|
||||
elseif(CMAKE_HOST_UNIX)
|
||||
set(EXECUTESUFFIX "")
|
||||
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
message(STATUS "Running on macOS")
|
||||
set(ARM_TOOLCHAIN_DIR "/opt/homebrew/bin")
|
||||
elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
|
||||
message(STATUS "Running on Linux (likely Ubuntu)")
|
||||
set(ARM_TOOLCHAIN_DIR "/opt/arm-none-eabi/bin")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Unknown host OS: ${CMAKE_HOST_SYSTEM_NAME}")
|
||||
endif()
|
||||
|
||||
set(BINUTILS_PATH ${ARM_TOOLCHAIN_DIR})
|
||||
|
||||
set(TOOLCHAIN_PREFIX arm-none-eabi-)
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}gcc${EXECUTESUFFIX})
|
||||
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
|
||||
set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}g++${EXECUTESUFFIX})
|
||||
set(CMAKE_LINKER ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}ld${EXECUTESUFFIX})
|
||||
set(CMAKE_OBJCOPY ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}objcopy${EXECUTESUFFIX} CACHE INTERNAL "objcopy tool")
|
||||
set(CMAKE_SIZE ${ARM_TOOLCHAIN_DIR}/${TOOLCHAIN_PREFIX}size${EXECUTESUFFIX} CACHE INTERNAL "size tool")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${BINUTILS_PATH})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
@@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.15.3)
|
||||
|
||||
file(GLOB FREERTO_KERNEL_SOURCES "${NRF_SDK_DIR}/external/freertos/source/*.c")
|
||||
|
||||
add_library(freertos OBJECT
|
||||
${NRF_SDK_DIR}/external/freertos/portable/GCC/nrf52/port.c
|
||||
${NRF_SDK_DIR}/external/freertos/portable/CMSIS/nrf52/port_cmsis.c
|
||||
${NRF_SDK_DIR}/external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c
|
||||
${NRF_SDK_DIR}/external/freertos/source/portable/MemMang/heap_4.c
|
||||
${FREERTO_KERNEL_SOURCES}
|
||||
)
|
||||
|
||||
target_include_directories(freertos PUBLIC
|
||||
${NRF_SDK_DIR}/external/freertos/portable/CMSIS/nrf52
|
||||
${NRF_SDK_DIR}/external/freertos/portable/GCC/nrf52
|
||||
${NRF_SDK_DIR}/external/freertos/source/include
|
||||
)
|
||||
|
||||
target_link_libraries(freertos PRIVATE
|
||||
prj_config
|
||||
)
|
||||
-342
@@ -1,342 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ble_advdata.h"
|
||||
|
||||
#include "nrf_ble_gatt.h"
|
||||
#include "nrf_ble_scan.h"
|
||||
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_ble.h"
|
||||
#include "nrf_sdh_freertos.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "message_buffer.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern uint32_t uart_drv_rx(void *, uint32_t);
|
||||
extern uint32_t uart_drv_tx(void *, uint32_t);
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} host_cmd_survive_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} host_cmd_scan_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t addr_type;
|
||||
uint8_t addr[6];
|
||||
} host_cmd_connect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} host_cmd_disconnect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t handle;
|
||||
uint8_t write_date[0];
|
||||
} host_cmd_write_char_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t handle;
|
||||
} host_cmd_read_char_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
union
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t payload[255];
|
||||
};
|
||||
} raw;
|
||||
|
||||
host_cmd_survive_t survive;
|
||||
host_cmd_scan_t scan;
|
||||
host_cmd_connect_t connect;
|
||||
host_cmd_disconnect_t disconnect;
|
||||
host_cmd_write_char_t write_char;
|
||||
host_cmd_read_char_t read_char;
|
||||
|
||||
} host_command_t;
|
||||
|
||||
#define CMD_NULL 0x00
|
||||
#define CMD_SURVIVE 0x0A
|
||||
#define CMD_SCAN 0x03
|
||||
#define CMD_CONNECT 0x05
|
||||
#define CMD_DISCONNECT 0x08
|
||||
#define CMD_WR_CHAR 0x06
|
||||
#define CMD_RD_CHAR 0x07
|
||||
#define CMD_SUFFIX 0xF1
|
||||
|
||||
static MessageBufferHandle_t host_cmd_msg;
|
||||
|
||||
static void survive_ack(void)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x01, 0x03 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
|
||||
void on_survive(host_cmd_survive_t *p_cmd)
|
||||
{
|
||||
survive_ack();
|
||||
}
|
||||
|
||||
static void connect_ack(void)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x04, 0x2E, 0x50, 0x30, 0x04 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
|
||||
static void on_connect(host_cmd_connect_t *p_cmd)
|
||||
{
|
||||
extern void le_scan_stop(void);
|
||||
extern void le_gap_connet(ble_gap_addr_t * p_peer_addr, nrf_ble_scan_t * p_scan);
|
||||
extern const nrf_ble_scan_t *le_scan_obj(void);
|
||||
|
||||
ble_gap_addr_t gap_addr;
|
||||
gap_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC;
|
||||
gap_addr.addr_id_peer = 0;
|
||||
for (int i = 0; i < COUNTOF(gap_addr.addr); i++)
|
||||
{
|
||||
gap_addr.addr[i] = p_cmd->addr[COUNTOF(gap_addr.addr) - i - 1];
|
||||
}
|
||||
le_gap_connet((void *)&gap_addr, (void *)le_scan_obj());
|
||||
|
||||
char rsp_buf[64];
|
||||
sprintf(rsp_buf, "%s(%02X:%02X:%02X:%02X:%02X:%02X)\r\n", __FUNCTION__, gap_addr.addr[5], gap_addr.addr[4], gap_addr.addr[3], gap_addr.addr[2], gap_addr.addr[1], gap_addr.addr[0]);
|
||||
NRF_LOG_INFO("%s", rsp_buf);
|
||||
}
|
||||
|
||||
static void disconnect_ack(void)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x01, 0x03 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
|
||||
static void on_disconnect(host_cmd_disconnect_t *p_cmd)
|
||||
{
|
||||
extern void le_gap_disconnet(uint16_t);
|
||||
le_gap_disconnet(0);
|
||||
}
|
||||
|
||||
static void on_scan(host_cmd_scan_t *p_cmd)
|
||||
{
|
||||
extern void le_scan_start(void);
|
||||
le_scan_start();
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const uint16_t company_identifier;
|
||||
struct
|
||||
{
|
||||
const uint8_t company_code[5];
|
||||
const uint8_t hw_ver[4];
|
||||
const uint16_t battery_level;
|
||||
} __PACKED data;
|
||||
} manu_spec_data_t;
|
||||
|
||||
void host_scan_filter_match_cb(
|
||||
void *p_manu_spec_data,
|
||||
uint32_t manu_spec_data_len,
|
||||
char *p_device_name,
|
||||
uint32_t device_name_len,
|
||||
ble_gap_addr_t const *peer_addr,
|
||||
int16_t rssi)
|
||||
{
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t hci_packet_event;
|
||||
uint8_t len;
|
||||
uint8_t addr[6];
|
||||
uint8_t product_module[4];
|
||||
uint32_t hw_ver;
|
||||
uint8_t buid_time[2];
|
||||
uint8_t parameter[3];
|
||||
uint16_t bat_volt;
|
||||
uint8_t dev_name[11];
|
||||
} __PACKED host_scan_rsp_t;
|
||||
|
||||
volatile host_scan_rsp_t host_scan_rsp = {
|
||||
.hci_packet_event = 0x0004,
|
||||
.product_module = { 'B', 'P', 'H', 'S' },
|
||||
.parameter = { 'B', 'A', 'T' },
|
||||
.buid_time = { 0x17, 0x06 },
|
||||
};
|
||||
|
||||
char peer_addr_str[(2 + 1) * BLE_GAP_ADDR_LEN + 1] = { 0 };
|
||||
if (peer_addr)
|
||||
{
|
||||
for (int i = 0; i < BLE_GAP_ADDR_LEN; i++)
|
||||
{
|
||||
host_scan_rsp.addr[i] = peer_addr->addr[(BLE_GAP_ADDR_LEN - 1) - i];
|
||||
}
|
||||
sprintf(peer_addr_str, "%02X:%02X:%02X:%02X:%02X:%02X", host_scan_rsp.addr[0], host_scan_rsp.addr[1], host_scan_rsp.addr[2], host_scan_rsp.addr[3], host_scan_rsp.addr[4], host_scan_rsp.addr[5]);
|
||||
}
|
||||
if (p_manu_spec_data)
|
||||
{
|
||||
manu_spec_data_t *p = p_manu_spec_data;
|
||||
memcpy((void *)&host_scan_rsp.hw_ver, &p->data.hw_ver[0], sizeof(p->data.hw_ver));
|
||||
uint16_t voltage = p->data.battery_level * 37;
|
||||
host_scan_rsp.bat_volt = __REVSH(voltage);
|
||||
}
|
||||
|
||||
host_scan_rsp.len = offsetof(host_scan_rsp_t, dev_name) - offsetof(host_scan_rsp_t, addr);
|
||||
if (p_device_name)
|
||||
{
|
||||
uint32_t len;
|
||||
len = sizeof(host_scan_rsp.dev_name);
|
||||
len = len > device_name_len ? device_name_len : len;
|
||||
memcpy((void *)host_scan_rsp.dev_name, p_device_name, len);
|
||||
host_scan_rsp.len += len;
|
||||
}
|
||||
|
||||
NRF_LOG_INFO("Found: %s [%s, %s, %08X, %d, %ddb]",
|
||||
host_scan_rsp.dev_name,
|
||||
peer_addr_str,
|
||||
host_scan_rsp.product_module,
|
||||
__REV(host_scan_rsp.hw_ver),
|
||||
__REVSH(host_scan_rsp.bat_volt),
|
||||
rssi);
|
||||
uint32_t tx_len = offsetof(host_scan_rsp_t, addr) + host_scan_rsp.len;
|
||||
uart_drv_tx((void *)&host_scan_rsp, offsetof(host_scan_rsp_t, addr) + host_scan_rsp.len);
|
||||
}
|
||||
|
||||
static void host_cmd_exec_task(void *p_arg)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
static uint8_t buf[256] = { 0 };
|
||||
host_command_t *p_cmd = (void *)buf;
|
||||
|
||||
p_cmd->raw.opcode = CMD_NULL;
|
||||
p_cmd->raw.len = 0;
|
||||
|
||||
size_t recv = xMessageBufferReceive(host_cmd_msg, buf, sizeof(buf), portMAX_DELAY);
|
||||
|
||||
switch (p_cmd->raw.opcode)
|
||||
{
|
||||
case CMD_SURVIVE:
|
||||
on_survive(&p_cmd->survive);
|
||||
break;
|
||||
case CMD_CONNECT:
|
||||
on_connect(&p_cmd->connect);
|
||||
break;
|
||||
case CMD_DISCONNECT:
|
||||
on_disconnect(&p_cmd->disconnect);
|
||||
break;
|
||||
case CMD_SCAN:
|
||||
on_scan(&p_cmd->scan);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void host_cmd_recv_task(void *p_arg)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
static uint8_t buf[256];
|
||||
|
||||
uint32_t recv = uart_drv_rx(buf, sizeof(buf));
|
||||
uint32_t offset = 0;
|
||||
|
||||
while (offset < recv)
|
||||
{
|
||||
host_command_t *p_cmd = (void *)&buf[offset];
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
|
||||
if (p_cmd->raw.payload[p_cmd->raw.len] == CMD_SUFFIX)
|
||||
{
|
||||
switch (p_cmd->raw.opcode)
|
||||
{
|
||||
case CMD_SURVIVE:
|
||||
xMessageBufferSend(host_cmd_msg, p_cmd, sizeof(host_cmd_survive_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(host_cmd_survive_t);
|
||||
break;
|
||||
case CMD_CONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_cmd, sizeof(host_cmd_connect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(host_cmd_connect_t);
|
||||
break;
|
||||
case CMD_DISCONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_cmd, sizeof(host_cmd_disconnect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(host_cmd_disconnect_t);
|
||||
break;
|
||||
case CMD_SCAN:
|
||||
xMessageBufferSend(host_cmd_msg, p_cmd, sizeof(host_cmd_scan_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(host_cmd_scan_t);
|
||||
break;
|
||||
default:
|
||||
offset++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset++;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void host_tasks_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
ret_code_t err_code;
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
connect_ack();
|
||||
break;
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
disconnect_ack();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void host_tasks_init(void)
|
||||
{
|
||||
host_cmd_msg = xMessageBufferCreate(1024);
|
||||
xTaskCreate(host_cmd_recv_task, "cmd_recv", 128, NULL, 5, NULL);
|
||||
xTaskCreate(host_cmd_exec_task, "cmd_exec", 512, NULL, 2, NULL);
|
||||
// Register a handler for BLE events.
|
||||
NRF_SDH_BLE_OBSERVER(m_tasks_observer, 3, host_tasks_handler, NULL);
|
||||
}
|
||||
-303
@@ -1,303 +0,0 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "ble_db_discovery.h"
|
||||
#include "ble_gattc.h"
|
||||
#include "ble_srv_common.h"
|
||||
|
||||
#include "nrf_ble_gq.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**< Used vendor specific UUID. */
|
||||
#define BLE_EIS_BASE_UUID \
|
||||
{ \
|
||||
0x4D, 0x3C, 0x56, 0x45, 0x12, 0x8B, 0x44, 0x1D, 0x8D, 0x6F, 0xC5, 0x95, 0x00, 0x00, 0x9B, 0xD8 \
|
||||
}
|
||||
#define BLE_UUID_EIS_SERVICE 0x0001
|
||||
#define BLE_UUID_EIS_REGULAR_DATA_CHAR 0x0002
|
||||
#define BLE_UUID_EIS_LOW_FREQ_DATA_CHAR 0x0003
|
||||
#define BLE_UUID_EIS_AUXILIARY_DATA_CHAR 0x0004
|
||||
#define BLE_UUID_EIS_STATUS_CHAR 0x0005
|
||||
#define BLE_UUID_EIS_EVENT_CHAR 0x0006
|
||||
|
||||
struct ble_eis_c_s
|
||||
{
|
||||
uint16_t conn_handle;
|
||||
void (*evt_handler)(ble_evt_t const *p_ble_evt, void *p_context);
|
||||
uint16_t regular_data_char_handle;
|
||||
uint16_t low_freq_data_char_handle;
|
||||
uint16_t auxiliary_data_char_handle;
|
||||
uint16_t status_char_handle;
|
||||
uint16_t event_char_handle;
|
||||
};
|
||||
|
||||
typedef struct ble_eis_c_s ble_eis_c_t;
|
||||
|
||||
static ble_eis_c_t m_eis_c;
|
||||
|
||||
static void on_disconnected(ble_eis_c_t *p_ble_eis_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
p_ble_eis_c->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
p_ble_eis_c->regular_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_ble_eis_c->auxiliary_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_ble_eis_c->status_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_ble_eis_c->event_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
static uint32_t hvx_cnt = 0;
|
||||
static TickType_t hvx_begin = 0;
|
||||
static void on_connected(ble_eis_c_t *p_ble_eis_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
hvx_cnt = 0;
|
||||
hvx_begin = 0;
|
||||
}
|
||||
|
||||
static void on_hvx(ble_eis_c_t *p_ble_eis_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
hvx_cnt++;
|
||||
if (hvx_begin == 0)
|
||||
{
|
||||
hvx_begin = xTaskGetTickCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
static char str[64];
|
||||
float kb = 8 * hvx_cnt * 240 / 1024.0;
|
||||
float timespan = (xTaskGetTickCount() - hvx_begin) / 1000.0;
|
||||
snprintf(str, sizeof(str), "%s(): %.2fkbps", __FUNCTION__, kb / timespan);
|
||||
NRF_LOG_INFO("%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
static void on_read_rsp(ble_eis_c_t *p_ble_eis_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
}
|
||||
|
||||
ret_code_t le_eis_ccdc_configure(uint16_t conn_handle, uint16_t char_handle, bool notification_enable)
|
||||
{
|
||||
if (conn_handle == BLE_CONN_HANDLE_INVALID)
|
||||
{
|
||||
__BKPT(255);
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (char_handle == BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
__BKPT(255);
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
NRF_LOG_INFO("Configuring CCCD Handle = 0x%04X, Connection Handle = 0x%04X",
|
||||
char_handle + 1,
|
||||
conn_handle);
|
||||
|
||||
nrf_ble_gq_req_t cccd_req;
|
||||
uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INVALID;
|
||||
uint8_t cccd[BLE_CCCD_VALUE_LEN];
|
||||
|
||||
cccd[0] = LSB_16(cccd_val);
|
||||
cccd[1] = MSB_16(cccd_val);
|
||||
|
||||
memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t));
|
||||
|
||||
cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE;
|
||||
cccd_req.params.gattc_write.handle = char_handle + 1;
|
||||
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;
|
||||
|
||||
extern nrf_ble_gq_t *le_gap_queue(void);
|
||||
return nrf_ble_gq_item_add(le_gap_queue(), &cccd_req, conn_handle);
|
||||
}
|
||||
|
||||
static void le_eis_c_evt_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
{
|
||||
ble_eis_c_t *p_ble_eis_c = (ble_eis_c_t *)p_context;
|
||||
|
||||
if ((p_ble_eis_c == NULL) || (p_ble_evt == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
on_disconnected(p_ble_eis_c, p_ble_evt);
|
||||
break;
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
on_connected(p_ble_eis_c, p_ble_evt);
|
||||
break;
|
||||
case BLE_GATTC_EVT_HVX:
|
||||
/*
|
||||
Handle Value Notification or Indication event.
|
||||
Confirm indication with @ref sd_ble_gattc_hv_confirm.
|
||||
See @ref ble_gattc_evt_hvx_t. */
|
||||
on_hvx(p_ble_eis_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP:
|
||||
/*
|
||||
Read Response event.
|
||||
See @ref ble_gattc_evt_read_rsp_t. */
|
||||
on_read_rsp(p_ble_eis_c, p_ble_evt);
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
/*
|
||||
Primary Service Discovery Response event.
|
||||
See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_REL_DISC_RSP:
|
||||
/*
|
||||
Relationship Discovery Response event.
|
||||
See @ref ble_gattc_evt_rel_disc_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||
/*
|
||||
Characteristic Discovery Response event.
|
||||
See @ref ble_gattc_evt_char_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP:
|
||||
/*
|
||||
Descriptor Discovery Response event.
|
||||
See @ref ble_gattc_evt_desc_disc_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP:
|
||||
/*
|
||||
Attribute Information Response event.
|
||||
See @ref ble_gattc_evt_attr_info_disc_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
|
||||
/*
|
||||
Read By UUID Response event.
|
||||
See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_CHAR_VALS_READ_RSP:
|
||||
/*
|
||||
Read multiple Response event.
|
||||
See @ref ble_gattc_evt_char_vals_read_rsp_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_WRITE_RSP:
|
||||
/*
|
||||
Write Response event.
|
||||
See @ref ble_gattc_evt_write_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
|
||||
/*
|
||||
Exchange MTU Response event.
|
||||
See @ref ble_gattc_evt_exchange_mtu_rsp_t. */
|
||||
break;
|
||||
case BLE_GATTC_EVT_TIMEOUT:
|
||||
/*
|
||||
Timeout event.
|
||||
See @ref ble_gattc_evt_timeout_t. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE:
|
||||
/*
|
||||
Write without Response transmission complete. */
|
||||
__BKPT(255);
|
||||
break;
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void le_eis_c_cccd_timer_cb(TimerHandle_t xTimer)
|
||||
{
|
||||
xTimerStop(xTimer, pdMS_TO_TICKS(0));
|
||||
le_eis_ccdc_configure(m_eis_c.conn_handle, m_eis_c.regular_data_char_handle, true);
|
||||
le_eis_ccdc_configure(m_eis_c.conn_handle, m_eis_c.low_freq_data_char_handle, true);
|
||||
le_eis_ccdc_configure(m_eis_c.conn_handle, m_eis_c.auxiliary_data_char_handle, true);
|
||||
le_eis_ccdc_configure(m_eis_c.conn_handle, m_eis_c.status_char_handle, true);
|
||||
le_eis_ccdc_configure(m_eis_c.conn_handle, m_eis_c.event_char_handle, true);
|
||||
NRF_LOG_INFO("Enable notifications. ");
|
||||
}
|
||||
|
||||
static TimerHandle_t le_eis_c_cccd_timer = NULL;
|
||||
|
||||
void le_eis_c_init(void)
|
||||
{
|
||||
m_eis_c.evt_handler = le_eis_c_evt_handler;
|
||||
m_eis_c.conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
m_eis_c.regular_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
m_eis_c.auxiliary_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
m_eis_c.status_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
m_eis_c.event_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
ble_uuid128_t base_uuid = { .uuid128 = BLE_EIS_BASE_UUID };
|
||||
ret_code_t err_code;
|
||||
uint8_t uuid_type;
|
||||
ble_uuid_t eis_uuid = {
|
||||
.type = BLE_UUID_TYPE_UNKNOWN,
|
||||
.uuid = BLE_UUID_EIS_SERVICE,
|
||||
};
|
||||
err_code = sd_ble_uuid_vs_add(&base_uuid, &eis_uuid.type);
|
||||
ble_db_discovery_evt_register(&eis_uuid);
|
||||
|
||||
NRF_SDH_BLE_OBSERVER(m_eis_c_observer, BLE_DIS_C_BLE_OBSERVER_PRIO, le_eis_c_evt_handler, &m_eis_c);
|
||||
|
||||
le_eis_c_cccd_timer = xTimerCreate("Timer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, le_eis_c_cccd_timer_cb);
|
||||
}
|
||||
|
||||
void le_eis_c_on_db_disc_evt(ble_db_discovery_evt_t *p_evt)
|
||||
{
|
||||
ble_gatt_db_char_t *p_chars = p_evt->params.discovered_db.charateristics;
|
||||
|
||||
// Check if the service discovery is necessary for the link and if the event handler is present.
|
||||
if (m_eis_c.evt_handler == NULL || m_eis_c.conn_handle == p_evt->conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the eis service was discovered.
|
||||
if ((p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_EIS_SERVICE) &&
|
||||
(p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_VENDOR_BEGIN))
|
||||
{
|
||||
m_eis_c.conn_handle = p_evt->conn_handle;
|
||||
|
||||
for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
|
||||
{
|
||||
switch (p_chars[i].characteristic.uuid.uuid)
|
||||
{
|
||||
case BLE_UUID_EIS_REGULAR_DATA_CHAR:
|
||||
m_eis_c.regular_data_char_handle = p_chars[i].characteristic.handle_value;
|
||||
break;
|
||||
case BLE_UUID_EIS_LOW_FREQ_DATA_CHAR:
|
||||
m_eis_c.low_freq_data_char_handle = p_chars[i].characteristic.handle_value;
|
||||
break;
|
||||
case BLE_UUID_EIS_AUXILIARY_DATA_CHAR:
|
||||
m_eis_c.auxiliary_data_char_handle = p_chars[i].characteristic.handle_value;
|
||||
break;
|
||||
case BLE_UUID_EIS_STATUS_CHAR:
|
||||
m_eis_c.status_char_handle = p_chars[i].characteristic.handle_value;
|
||||
break;
|
||||
case BLE_UUID_EIS_EVENT_CHAR:
|
||||
m_eis_c.event_char_handle = p_chars[i].characteristic.handle_value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
xTimerStart(le_eis_c_cccd_timer, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "app_config.h"
|
||||
#include "apply_old_config.h"
|
||||
#include "sdk_config.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#include "nrf_delay.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#include "nrf_sdh.h"
|
||||
#include "nrf_sdh_ble.h"
|
||||
#include "nrf_sdh_freertos.h"
|
||||
|
||||
#include "ble_advdata.h"
|
||||
#include "nrf_ble_scan.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
NRF_BLE_SCAN_DEF(m_scan); /**< Scanning Module instance. */
|
||||
|
||||
#define MAX_DEV_NAME_LEN ((BLE_GAP_ADV_SET_DATA_SIZE_MAX + 1) - AD_DATA_OFFSET)
|
||||
|
||||
static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
|
||||
{
|
||||
// Initialize advertisement report for parsing.
|
||||
ret_code_t err_code;
|
||||
uint16_t offset = 0;
|
||||
void *p_manu_spec_data = NULL;
|
||||
char dev_name[MAX_DEV_NAME_LEN];
|
||||
memset(dev_name, 0x00, MAX_DEV_NAME_LEN);
|
||||
|
||||
// Search for advertising manufacturer spec data
|
||||
uint32_t manu_spec_data_len = ble_advdata_search(p_adv_report->data.p_data,
|
||||
p_adv_report->data.len,
|
||||
&offset,
|
||||
BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA);
|
||||
if (manu_spec_data_len)
|
||||
{
|
||||
p_manu_spec_data = &p_adv_report->data.p_data[offset];
|
||||
}
|
||||
|
||||
// Search for advertising names.
|
||||
uint32_t device_name_len = ble_advdata_search(p_adv_report->data.p_data,
|
||||
p_adv_report->data.len,
|
||||
&offset,
|
||||
BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME);
|
||||
if (device_name_len)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)p_adv_report->data.p_data;
|
||||
memcpy(dev_name, &p[offset], device_name_len);
|
||||
}
|
||||
extern void host_scan_filter_match_cb(
|
||||
void *p_manu_spec_data,
|
||||
uint32_t manu_spec_data_len,
|
||||
char *p_device_name,
|
||||
uint32_t device_name_len,
|
||||
ble_gap_addr_t const *peer_addr,
|
||||
int16_t rssi);
|
||||
host_scan_filter_match_cb(
|
||||
p_manu_spec_data,
|
||||
manu_spec_data_len,
|
||||
dev_name,
|
||||
device_name_len,
|
||||
&p_adv_report->peer_addr,
|
||||
p_adv_report->rssi);
|
||||
}
|
||||
|
||||
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: {
|
||||
/**< Error occurred when establishing the connection.
|
||||
In this event, an error is passed from the function call @ref sd_ble_gap_connect. */
|
||||
err_code = p_scan_evt->params.connecting_err.err_code;
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
break;
|
||||
case NRF_BLE_SCAN_EVT_FILTER_MATCH: {
|
||||
/**< A filter is matched or all filters are matched in the multifilter mode. */
|
||||
on_adv_report(p_scan_evt->params.filter_match.p_adv_report);
|
||||
}
|
||||
break;
|
||||
case NRF_BLE_SCAN_EVT_CONNECTED:
|
||||
/**< Connected to device. */
|
||||
break;
|
||||
case NRF_BLE_SCAN_EVT_WHITELIST_REQUEST:
|
||||
/**< Request the whitelist from the main application. For whitelist scanning to work, the whitelist must be set when this event occurs. */
|
||||
break;
|
||||
case NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT:
|
||||
/**< Send notification to the main application when a device from the whitelist is found. */
|
||||
break;
|
||||
case NRF_BLE_SCAN_EVT_NOT_FOUND:
|
||||
/**< The filter was not matched for the scan data. */
|
||||
break;
|
||||
case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
|
||||
/**< Scan timeout. */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static char const *m_target_periph_name[] = ELITE_DEVICE_NAME_LIST;
|
||||
|
||||
void le_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 = false;
|
||||
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);
|
||||
|
||||
for (int i = 0; i < COUNTOF(m_target_periph_name); i++)
|
||||
{
|
||||
err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_NAME_FILTER, m_target_periph_name[i]);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_NAME_FILTER, false);
|
||||
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
|
||||
void le_scan_start(void)
|
||||
{
|
||||
ret_code_t ret;
|
||||
NRF_LOG_INFO("Start scanning for device name \"%s\", \"%s\".",
|
||||
(uint32_t)m_target_periph_name[0],
|
||||
(uint32_t)m_target_periph_name[1]);
|
||||
ret = nrf_ble_scan_start(&m_scan);
|
||||
APP_ERROR_CHECK(ret);
|
||||
}
|
||||
|
||||
void le_scan_stop(void)
|
||||
{
|
||||
NRF_LOG_INFO("Stop scanning.");
|
||||
nrf_ble_scan_stop();
|
||||
}
|
||||
|
||||
const nrf_ble_scan_t *le_scan_obj(void)
|
||||
{
|
||||
return &m_scan;
|
||||
}
|
||||
@@ -1,21 +1,15 @@
|
||||
/* Linker script for nRF52811_XXAA */
|
||||
/* Linker script for nRF52840_XXAA */
|
||||
|
||||
GROUP(S140_softdevice.o)
|
||||
MEMORY
|
||||
{
|
||||
FLASH_SOFTDEVICE (rx) : ORIGIN = 0x00000000, LENGTH = 0x00027000
|
||||
FLASH (rx) : ORIGIN = 0x00027000, LENGTH = 0x000d9000
|
||||
EXTFLASH (rx) : ORIGIN = 0x12000000, LENGTH = 0x8000000
|
||||
RAM_SOFTDEVICE (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000
|
||||
RAM (rwx) : ORIGIN = 0x20010000, LENGTH = 0x0002F000
|
||||
RTT (rwx) : ORIGIN = 0x2003F000, LENGTH = 0x00001000
|
||||
CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x6000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.segger_rtt (NOLOAD) :
|
||||
{
|
||||
} > RTT
|
||||
CODE_RAM (rwx) : ORIGIN = 0x800000, LENGTH = 0x40000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -23,14 +17,12 @@ SECTIONS
|
||||
.softdevice :
|
||||
{
|
||||
KEEP(*(.softdevice))
|
||||
FILL(0xFFFFFFFF);
|
||||
. = 0x00027000;
|
||||
} > FLASH_SOFTDEVICE
|
||||
|
||||
.softdevice_sram :
|
||||
{
|
||||
FILL(0xFFFFFFFF);
|
||||
. = 0x000079e0;
|
||||
. = 0x00010000;
|
||||
} > RAM_SOFTDEVICE
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
SECTIONS
|
||||
{
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.mem_section_dummy_ram :
|
||||
{
|
||||
}
|
||||
.cli_sorted_cmd_ptrs :
|
||||
{
|
||||
PROVIDE(__start_cli_sorted_cmd_ptrs = .);
|
||||
KEEP(*(.cli_sorted_cmd_ptrs))
|
||||
PROVIDE(__stop_cli_sorted_cmd_ptrs = .);
|
||||
} > RAM
|
||||
.fs_data :
|
||||
{
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
} > RAM
|
||||
.log_dynamic_data :
|
||||
{
|
||||
PROVIDE(__start_log_dynamic_data = .);
|
||||
KEEP(*(SORT(.log_dynamic_data*)))
|
||||
PROVIDE(__stop_log_dynamic_data = .);
|
||||
} > RAM
|
||||
.log_filter_data :
|
||||
{
|
||||
PROVIDE(__start_log_filter_data = .);
|
||||
KEEP(*(SORT(.log_filter_data*)))
|
||||
PROVIDE(__stop_log_filter_data = .);
|
||||
} > RAM
|
||||
|
||||
} INSERT AFTER .data;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.mem_section_dummy_rom :
|
||||
{
|
||||
}
|
||||
.sdh_soc_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_soc_observers = .);
|
||||
KEEP(*(SORT(.sdh_soc_observers*)))
|
||||
PROVIDE(__stop_sdh_soc_observers = .);
|
||||
} > FLASH
|
||||
.sdh_ble_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_ble_observers = .);
|
||||
KEEP(*(SORT(.sdh_ble_observers*)))
|
||||
PROVIDE(__stop_sdh_ble_observers = .);
|
||||
} > FLASH
|
||||
.pwr_mgmt_data :
|
||||
{
|
||||
PROVIDE(__start_pwr_mgmt_data = .);
|
||||
KEEP(*(SORT(.pwr_mgmt_data*)))
|
||||
PROVIDE(__stop_pwr_mgmt_data = .);
|
||||
} > FLASH
|
||||
.sdh_req_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_req_observers = .);
|
||||
KEEP(*(SORT(.sdh_req_observers*)))
|
||||
PROVIDE(__stop_sdh_req_observers = .);
|
||||
} > FLASH
|
||||
.sdh_state_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_state_observers = .);
|
||||
KEEP(*(SORT(.sdh_state_observers*)))
|
||||
PROVIDE(__stop_sdh_state_observers = .);
|
||||
} > FLASH
|
||||
.sdh_stack_observers :
|
||||
{
|
||||
PROVIDE(__start_sdh_stack_observers = .);
|
||||
KEEP(*(SORT(.sdh_stack_observers*)))
|
||||
PROVIDE(__stop_sdh_stack_observers = .);
|
||||
} > FLASH
|
||||
.nrf_queue :
|
||||
{
|
||||
PROVIDE(__start_nrf_queue = .);
|
||||
KEEP(*(.nrf_queue))
|
||||
PROVIDE(__stop_nrf_queue = .);
|
||||
} > FLASH
|
||||
.nrf_balloc :
|
||||
{
|
||||
PROVIDE(__start_nrf_balloc = .);
|
||||
KEEP(*(.nrf_balloc))
|
||||
PROVIDE(__stop_nrf_balloc = .);
|
||||
} > FLASH
|
||||
.cli_command :
|
||||
{
|
||||
PROVIDE(__start_cli_command = .);
|
||||
KEEP(*(.cli_command))
|
||||
PROVIDE(__stop_cli_command = .);
|
||||
} > FLASH
|
||||
.crypto_data :
|
||||
{
|
||||
PROVIDE(__start_crypto_data = .);
|
||||
KEEP(*(SORT(.crypto_data*)))
|
||||
PROVIDE(__stop_crypto_data = .);
|
||||
} > FLASH
|
||||
.log_const_data :
|
||||
{
|
||||
PROVIDE(__start_log_const_data = .);
|
||||
KEEP(*(SORT(.log_const_data*)))
|
||||
PROVIDE(__stop_log_const_data = .);
|
||||
} > FLASH
|
||||
.log_backends :
|
||||
{
|
||||
PROVIDE(__start_log_backends = .);
|
||||
KEEP(*(SORT(.log_backends*)))
|
||||
PROVIDE(__stop_log_backends = .);
|
||||
} > FLASH
|
||||
|
||||
} INSERT AFTER .text
|
||||
|
||||
|
||||
INCLUDE "nrf_common.ld"
|
||||
|
||||
PROVIDE(_sbss = __bss_start__);
|
||||
PROVIDE(_ebss = __bss_end__);
|
||||
PROVIDE(_sdata = __data_start__);
|
||||
PROVIDE(_sidata = __etext);
|
||||
PROVIDE(_estack = __StackTop);
|
||||
PROVIDE(_edata = __data_end__);
|
||||
PROVIDE(__isr_vector = __StackTop);
|
||||
PROVIDE(_etext = __etext);
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
<Link>
|
||||
<LinkerScript Condition="'%(Link.LinkerScript)' == ''">$(BSP_ROOT)/nRF5x/LinkerScripts/nRF52840_XXAA_S140_reserve.lds</LinkerScript>
|
||||
<LibrarySearchDirectories>$(BSP_ROOT)/nRF5x/SoftdeviceLibraries/hard;$(BSP_ROOT)/nRF5x/LinkerScripts;%(Link.LibrarySearchDirectories)</LibrarySearchDirectories>
|
||||
<AdditionalOptions>--specs=nano.specs -u _printf_float --specs=nosys.specs -mabi=aapcs %(Link.AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>--specs=nano.specs -u _printf_float --specs=nosys.specs -Wl,--no-warn-rwx-segments -mabi=aapcs %(Link.AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<EmbeddedProfile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ToolchainID>com.visualgdb.arm-eabi</ToolchainID>
|
||||
<ToolchainVersion>
|
||||
<GCC>10.3.1</GCC>
|
||||
<GDB>10.2.90</GDB>
|
||||
<Revision>1</Revision>
|
||||
<GCC>14.2.1</GCC>
|
||||
<GDB>15.2</GDB>
|
||||
<Revision>2</Revision>
|
||||
</ToolchainVersion>
|
||||
<BspID>com.sysprogs.arm.nordic.nrf5x</BspID>
|
||||
<BspVersion>17.0</BspVersion>
|
||||
|
||||
+53
-14
@@ -7,12 +7,13 @@ def survive_cmd(ser):
|
||||
send = [0x0A, 0x01, 0xF1]
|
||||
ser.write(send)
|
||||
read = ser.read(4)
|
||||
print("recv: "+" ".join("%02X" % b for b in read))
|
||||
print("recv: " + " ".join("%02X" % b for b in read))
|
||||
|
||||
def scan_cmd(ser, is_raw_data = True):
|
||||
|
||||
def scan_cmd(ser, is_raw_data=True):
|
||||
send = [0x03, 0x01, 0xF1]
|
||||
ser.write(send)
|
||||
peer_addr = []
|
||||
peer_addr = []
|
||||
for i in range(10):
|
||||
hci_packet_event = ser.read(2)
|
||||
if int.from_bytes(hci_packet_event, "little") != 0x0004:
|
||||
@@ -36,38 +37,76 @@ def scan_cmd(ser, is_raw_data = True):
|
||||
print(" hw version: " + " ".join("%02X" % b for b in payload[10:14]))
|
||||
print(" build time: " + " ".join("%02X" % b for b in payload[14:16]))
|
||||
print(" Parameter1: " + str(payload[16:19], "utf-8"))
|
||||
print(" battery volt: " + str(int.from_bytes(payload[19:21], "big")/1000.0) + "V")
|
||||
print(" device name: " + str(payload[21:], "utf-8"))
|
||||
print(
|
||||
" battery volt: "
|
||||
+ str(int.from_bytes(payload[19:21], "big") / 1000.0)
|
||||
+ "V"
|
||||
)
|
||||
print(" device name: " + str(payload[21:], "utf-8"))
|
||||
return peer_addr
|
||||
|
||||
def connect(ser, peer_addr = []):
|
||||
|
||||
def connect(ser, peer_addr=[]):
|
||||
send = [0x05, 0x08, 0x00]
|
||||
send += peer_addr
|
||||
send += [0xF1]
|
||||
ser.write(send)
|
||||
read = ser.read(7)
|
||||
print("recv: "+" ".join("%02X" % b for b in read))
|
||||
read = ser.read(4)
|
||||
print("recv: " + " ".join("%02X" % b for b in read))
|
||||
|
||||
|
||||
def disconnect(ser):
|
||||
send = [0x08, 0x01, 0xF1]
|
||||
ser.write(send)
|
||||
read = ser.read(4)
|
||||
print("recv: "+" ".join("%02X" % b for b in read))
|
||||
print("recv: " + " ".join("%02X" % b for b in read))
|
||||
|
||||
|
||||
def write_char(ser: serial.Serial, handle: int, write_data: tuple):
|
||||
send = [0x06, len(write_data)+2, handle]
|
||||
send += write_data
|
||||
send += [0xF1]
|
||||
ser.write(send)
|
||||
|
||||
def read_char(ser: serial.Serial, handle: int):
|
||||
send = [0x07, 0x02, handle, 0xF1]
|
||||
ser.write(send)
|
||||
read = ser.read(0xFFFF)
|
||||
print("recv: " + " ".join("%02X" % b for b in read))
|
||||
|
||||
|
||||
def main():
|
||||
# set comport
|
||||
ser = serial.Serial("COM12", 57600, 8)
|
||||
ser = serial.Serial("COM15", 57600, 8, inter_byte_timeout=0.01)
|
||||
|
||||
# send survive cmd
|
||||
survive_cmd(ser)
|
||||
survive_cmd(ser)
|
||||
|
||||
# send scan cmd
|
||||
peer_addr = scan_cmd(ser, False)
|
||||
|
||||
peer_addr = scan_cmd(ser, False)
|
||||
time.sleep(10)
|
||||
return
|
||||
# send connect cmd with peer addr
|
||||
connect(ser, peer_addr)
|
||||
time.sleep(10)
|
||||
time.sleep(3)
|
||||
|
||||
# send write char to enable notify
|
||||
write_char(ser, 0x0024, [0xc4,0xf0,0xf1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
|
||||
time.sleep(0.1)
|
||||
write_char(ser, 0x0024, [0x74,0x10,0xf1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
|
||||
time.sleep(0.1)
|
||||
read_char(ser, 0x0021)
|
||||
# 130500040000000000000000000000000000001c
|
||||
time.sleep(0.2)
|
||||
# send write char to enable notify
|
||||
#write_char(ser, 0x0028, 1)
|
||||
#time.sleep(5)
|
||||
|
||||
# send write char to disable notify
|
||||
#write_char(ser, 0x0028, 0)
|
||||
|
||||
# send read char to disable notify
|
||||
#read_char(ser, 0x0027)
|
||||
|
||||
# send disconnect cmd
|
||||
disconnect(ser)
|
||||
|
||||
Reference in New Issue
Block a user