2017-05-15 16:12:15 +08:00
# include "nordic_common.h"
# include "nrf.h"
# include "ble_hci.h"
# include "ble_advdata.h"
# include "ble_advertising.h"
# include "ble_conn_params.h"
# include "softdevice_handler.h"
# include "nrf_ble_gatt.h"
# include "app_timer.h"
# include "ble_nus.h"
# include "app_util_platform.h"
# include <rtthread.h>
typedef rt_size_t ( * BLE_NOTIFY_T ) ( rt_uint8_t * buf , rt_uint16_t size ) ;
# define STACK_EVT_MQ_NUM 10
# define FAST_ADV() \
do { \
uint32_t err_code ; \
err_code = ble_advertising_start ( BLE_ADV_MODE_FAST ) ; \
APP_ERROR_CHECK ( err_code ) ; \
} while ( 0 )
typedef enum
{
STACK_EV_DISCON = 1 ,
STACK_EV_DISPATCH = 2 ,
STACK_EV_KEY = 4 ,
} STACK_EV_E ;
typedef struct
{
rt_list_t node ;
void * evt ;
} evt_list_t ;
typedef enum
{
STACK_STATE_IDLE = 0 ,
STACK_STATE_ADV = 1 ,
STACK_STATE_CON = 2 ,
STACK_STATE_DISC = 3
} STACK_STATE_E ;
STACK_STATE_E stack_state = STACK_STATE_IDLE ;
rt_event_t stack_event ;
rt_sem_t sd_evt_sem ;
rt_mq_t stack_evt_mq ;
rt_uint8_t * evt_sample ;
BLE_NOTIFY_T rx_notify = RT_NULL ;
// Low frequency clock source to be used by the SoftDevice
# define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \
. rc_ctiv = 0 , \
. rc_temp_ctiv = 0 , \
. xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM }
# define CONN_CFG_TAG 1 /**< A tag that refers to the BLE stack configuration we set with @ref sd_ble_cfg_set. Default tag is @ref BLE_CONN_CFG_TAG_DEFAULT. */
# define APP_FEATURE_NOT_SUPPORTED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 /**< Reply when unsupported features are requested. */
# define DEVICE_NAME "Nordic_UART" /**< Name of device. Will be included in the advertising data. */
# define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
# define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
# define APP_ADV_TIMEOUT_IN_SECONDS 30 /**< The advertising timeout (in units of seconds). */
# define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
# define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
# define SLAVE_LATENCY 0 /**< Slave latency. */
# define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
# define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
# define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
# define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
# define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
# define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */
# define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */
static ble_nus_t m_nus ; /**< Structure to identify the Nordic UART Service. */
static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID ; /**< Handle of the current connection. */
static nrf_ble_gatt_t m_gatt ; /**< GATT module instance. */
static ble_uuid_t m_adv_uuids [ ] = { { BLE_UUID_NUS_SERVICE , NUS_SERVICE_UUID_TYPE } } ; /**< Universally unique service identifier. */
static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3 ; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
/**@brief Function for assert macro callback.
*
* @ details This function will be called in case of an assert in the SoftDevice .
*
* @ warning This handler is an example only and does not fit a final product . You need to analyse
* how your product is supposed to react in case of Assert .
* @ warning On assert from the SoftDevice , the system can only recover on reset .
*
* @ param [ in ] line_num Line number of the failing ASSERT call .
* @ param [ in ] p_file_name File name of the failing ASSERT call .
*/
void assert_nrf_callback ( uint16_t line_num , const uint8_t * p_file_name )
{
app_error_handler ( DEAD_BEEF , line_num , p_file_name ) ;
}
/**@brief Function for the GAP initialization.
*
* @ details This function will set up all the necessary GAP ( Generic Access Profile ) parameters of
* the device . It also sets the permissions and appearance .
*/
static void gap_params_init ( void )
{
uint32_t err_code ;
ble_gap_conn_params_t gap_conn_params ;
ble_gap_conn_sec_mode_t sec_mode ;
BLE_GAP_CONN_SEC_MODE_SET_OPEN ( & sec_mode ) ;
err_code = sd_ble_gap_device_name_set ( & sec_mode ,
( const uint8_t * ) DEVICE_NAME ,
strlen ( DEVICE_NAME ) ) ;
APP_ERROR_CHECK ( err_code ) ;
memset ( & gap_conn_params , 0 , sizeof ( gap_conn_params ) ) ;
gap_conn_params . min_conn_interval = MIN_CONN_INTERVAL ;
gap_conn_params . max_conn_interval = MAX_CONN_INTERVAL ;
gap_conn_params . slave_latency = SLAVE_LATENCY ;
gap_conn_params . conn_sup_timeout = CONN_SUP_TIMEOUT ;
err_code = sd_ble_gap_ppcp_set ( & gap_conn_params ) ;
APP_ERROR_CHECK ( err_code ) ;
}
/**@brief Function for handling the data from the Nordic UART Service.
*
* @ details This function will process the data received from the Nordic UART BLE Service and send
* it to the UART module .
*
* @ param [ in ] p_nus Nordic UART Service structure .
* @ param [ in ] p_data Data to be send to UART module .
* @ param [ in ] length Length of the data .
*/
/**@snippet [Handling the data received over BLE] */
static void nus_data_handler ( ble_nus_t * p_nus , uint8_t * p_data , uint16_t length )
{
rt_kprintf ( " Received data from BLE NUS. Writing data on UART. \r \n " ) ;
for ( uint32_t i = 0 ; i < length ; i + + )
{
rt_kprintf ( " %02x " , p_data [ i ] ) ;
}
// ble_send(p_data, length);
if ( rx_notify ! = RT_NULL )
{
rx_notify ( p_data , length ) ;
}
}
/**@snippet [Handling the data received over BLE] */
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init ( void )
{
uint32_t err_code ;
ble_nus_init_t nus_init ;
memset ( & nus_init , 0 , sizeof ( nus_init ) ) ;
nus_init . data_handler = nus_data_handler ;
err_code = ble_nus_init ( & m_nus , & nus_init ) ;
APP_ERROR_CHECK ( err_code ) ;
}
/**@brief Function for handling an event from the Connection Parameters Module.
*
* @ details This function will be called for all events in the Connection Parameters Module
* which are passed to the application .
*
* @ note All this function does is to disconnect . This could have been done by simply setting
* the disconnect_on_fail config parameter , but instead we use the event handler
* mechanism to demonstrate its use .
*
* @ param [ in ] p_evt Event received from the Connection Parameters Module .
*/
static void on_conn_params_evt ( ble_conn_params_evt_t * p_evt )
{
uint32_t err_code ;
if ( p_evt - > evt_type = = BLE_CONN_PARAMS_EVT_FAILED )
{
err_code = sd_ble_gap_disconnect ( m_conn_handle , BLE_HCI_CONN_INTERVAL_UNACCEPTABLE ) ;
APP_ERROR_CHECK ( err_code ) ;
}
}
/**@brief Function for handling errors from the Connection Parameters module.
*
* @ param [ in ] nrf_error Error code containing information about what went wrong .
*/
static void conn_params_error_handler ( uint32_t nrf_error )
{
APP_ERROR_HANDLER ( nrf_error ) ;
}
/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init ( void )
{
uint32_t err_code ;
ble_conn_params_init_t cp_init ;
memset ( & cp_init , 0 , sizeof ( cp_init ) ) ;
cp_init . p_conn_params = NULL ;
cp_init . first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY ;
cp_init . next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY ;
cp_init . max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT ;
cp_init . start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID ;
cp_init . disconnect_on_fail = false ;
cp_init . evt_handler = on_conn_params_evt ;
cp_init . error_handler = conn_params_error_handler ;
err_code = ble_conn_params_init ( & cp_init ) ;
APP_ERROR_CHECK ( err_code ) ;
}
/**@brief Function for handling advertising events.
*
* @ details This function will be called for advertising events which are passed to the application .
*
* @ param [ in ] ble_adv_evt Advertising event .
*/
static void on_adv_evt ( ble_adv_evt_t ble_adv_evt )
{
// uint32_t err_code;
switch ( ble_adv_evt )
{
case BLE_ADV_EVT_FAST :
// err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
// APP_ERROR_CHECK(err_code);
stack_state = STACK_STATE_ADV ;
rt_kprintf ( " fast advert \n " ) ;
break ;
case BLE_ADV_EVT_IDLE :
// sleep_mode_enter();
stack_state = STACK_STATE_IDLE ;
rt_kprintf ( " advert idle \n " ) ;
break ;
default :
break ;
}
}
/**@brief Function for the application's SoftDevice event handler.
*
* @ param [ in ] p_ble_evt SoftDevice event .
*/
static void on_ble_evt ( ble_evt_t * p_ble_evt )
{
uint32_t err_code ;
switch ( p_ble_evt - > header . evt_id )
{
case BLE_GAP_EVT_CONNECTED :
// err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
// APP_ERROR_CHECK(err_code);
m_conn_handle = p_ble_evt - > evt . gap_evt . conn_handle ;
stack_state = STACK_STATE_CON ;
rt_kprintf ( " Connected \r \n " ) ;
break ; // BLE_GAP_EVT_CONNECTED
case BLE_GAP_EVT_DISCONNECTED :
// err_code = bsp_indication_set(BSP_INDICATE_IDLE);
// APP_ERROR_CHECK(err_code);
m_conn_handle = BLE_CONN_HANDLE_INVALID ;
stack_state = STACK_STATE_DISC ;
rt_kprintf ( " Disconnected \r \n " ) ;
break ; // BLE_GAP_EVT_DISCONNECTED
case BLE_GAP_EVT_SEC_PARAMS_REQUEST :
// Pairing not supported
err_code = sd_ble_gap_sec_params_reply ( m_conn_handle , BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP , NULL , NULL ) ;
APP_ERROR_CHECK ( err_code ) ;
break ; // BLE_GAP_EVT_SEC_PARAMS_REQUEST
case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST :
{
ble_gap_data_length_params_t dl_params ;
// Clearing the struct will effectivly set members to @ref BLE_GAP_DATA_LENGTH_AUTO
memset ( & dl_params , 0 , sizeof ( ble_gap_data_length_params_t ) ) ;
err_code = sd_ble_gap_data_length_update ( p_ble_evt - > evt . gap_evt . conn_handle , & dl_params , NULL ) ;
APP_ERROR_CHECK ( err_code ) ;
} break ;
case BLE_GATTS_EVT_SYS_ATTR_MISSING :
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set ( m_conn_handle , NULL , 0 , 0 ) ;
APP_ERROR_CHECK ( err_code ) ;
break ; // BLE_GATTS_EVT_SYS_ATTR_MISSING
case BLE_GATTC_EVT_TIMEOUT :
// Disconnect on GATT Client timeout event.
err_code = sd_ble_gap_disconnect ( p_ble_evt - > evt . gattc_evt . conn_handle ,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION ) ;
APP_ERROR_CHECK ( err_code ) ;
break ; // BLE_GATTC_EVT_TIMEOUT
case BLE_GATTS_EVT_TIMEOUT :
// Disconnect on GATT Server timeout event.
err_code = sd_ble_gap_disconnect ( p_ble_evt - > evt . gatts_evt . conn_handle ,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION ) ;
APP_ERROR_CHECK ( err_code ) ;
break ; // BLE_GATTS_EVT_TIMEOUT
case BLE_EVT_USER_MEM_REQUEST :
err_code = sd_ble_user_mem_reply ( p_ble_evt - > evt . gattc_evt . conn_handle , NULL ) ;
APP_ERROR_CHECK ( err_code ) ;
break ; // BLE_EVT_USER_MEM_REQUEST
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST :
{
ble_gatts_evt_rw_authorize_request_t req ;
ble_gatts_rw_authorize_reply_params_t auth_reply ;
req = p_ble_evt - > evt . gatts_evt . params . authorize_request ;
if ( req . type ! = BLE_GATTS_AUTHORIZE_TYPE_INVALID )
{
if ( ( req . request . write . op = = BLE_GATTS_OP_PREP_WRITE_REQ ) | |
( req . request . write . op = = BLE_GATTS_OP_EXEC_WRITE_REQ_NOW ) | |
( req . request . write . op = = BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL ) )
{
if ( req . type = = BLE_GATTS_AUTHORIZE_TYPE_WRITE )
{
auth_reply . type = BLE_GATTS_AUTHORIZE_TYPE_WRITE ;
}
else
{
auth_reply . type = BLE_GATTS_AUTHORIZE_TYPE_READ ;
}
auth_reply . params . write . gatt_status = APP_FEATURE_NOT_SUPPORTED ;
err_code = sd_ble_gatts_rw_authorize_reply ( p_ble_evt - > evt . gatts_evt . conn_handle ,
& auth_reply ) ;
APP_ERROR_CHECK ( err_code ) ;
}
}
} break ; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST
default :
// No implementation needed.
break ;
}
}
/**@brief Function for dispatching a SoftDevice event to all modules with a SoftDevice
* event handler .
*
* @ details This function is called from the SoftDevice event interrupt handler after a
* SoftDevice event has been received .
*
* @ param [ in ] p_ble_evt SoftDevice event .
*/
static void ble_evt_dispatch ( ble_evt_t * p_ble_evt )
{
if ( rt_mq_send ( stack_evt_mq , p_ble_evt , p_ble_evt - > header . evt_len ) ! = RT_EOK )
{
rt_kprintf ( " dispatch malloc failure \n " ) ;
}
else
{
rt_event_send ( stack_event , STACK_EV_DISPATCH ) ;
}
}
static rt_err_t evt_dispatch_worker ( void )
{
ble_evt_t * p_ble_evt = ( ble_evt_t * ) evt_sample ;
rt_err_t err ;
err = rt_mq_recv ( stack_evt_mq , ( void * ) evt_sample , BLE_STACK_EVT_MSG_BUF_SIZE , RT_WAITING_NO ) ;
if ( RT_EOK = = err )
{
ble_conn_params_on_ble_evt ( p_ble_evt ) ;
nrf_ble_gatt_on_ble_evt ( & m_gatt , p_ble_evt ) ;
ble_nus_on_ble_evt ( & m_nus , p_ble_evt ) ;
on_ble_evt ( p_ble_evt ) ;
ble_advertising_on_ble_evt ( p_ble_evt ) ;
// bsp_btn_ble_on_ble_evt(p_ble_evt);
rt_kprintf ( " ble evt dispatch \n " ) ;
}
return err ;
}
static uint32_t _softdevice_evt_schedule ( void )
{
rt_sem_release ( sd_evt_sem ) ;
return NRF_SUCCESS ;
}
/**@brief Function for the SoftDevice initialization.
*
* @ details This function initializes the SoftDevice and the BLE event interrupt .
*/
static void ble_stack_init ( void )
{
uint32_t err_code ;
nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC ;
// Initialize SoftDevice.
SOFTDEVICE_HANDLER_INIT ( & clock_lf_cfg , _softdevice_evt_schedule ) ;
// Fetch the start address of the application RAM.
uint32_t ram_start = 0 ;
err_code = softdevice_app_ram_start_get ( & ram_start ) ;
APP_ERROR_CHECK ( err_code ) ;
// Overwrite some of the default configurations for the BLE stack.
ble_cfg_t ble_cfg ;
// Configure the maximum number of connections.
memset ( & ble_cfg , 0 , sizeof ( ble_cfg ) ) ;
ble_cfg . gap_cfg . role_count_cfg . periph_role_count = BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT ;
ble_cfg . gap_cfg . role_count_cfg . central_role_count = 0 ;
ble_cfg . gap_cfg . role_count_cfg . central_sec_count = 0 ;
err_code = sd_ble_cfg_set ( BLE_GAP_CFG_ROLE_COUNT , & ble_cfg , ram_start ) ;
APP_ERROR_CHECK ( err_code ) ;
// Configure the maximum ATT MTU.
memset ( & ble_cfg , 0x00 , sizeof ( ble_cfg ) ) ;
ble_cfg . conn_cfg . conn_cfg_tag = CONN_CFG_TAG ;
ble_cfg . conn_cfg . params . gatt_conn_cfg . att_mtu = NRF_BLE_GATT_MAX_MTU_SIZE ;
err_code = sd_ble_cfg_set ( BLE_CONN_CFG_GATT , & ble_cfg , ram_start ) ;
APP_ERROR_CHECK ( err_code ) ;
// Configure the maximum event length.
memset ( & ble_cfg , 0x00 , sizeof ( ble_cfg ) ) ;
ble_cfg . conn_cfg . conn_cfg_tag = CONN_CFG_TAG ;
ble_cfg . conn_cfg . params . gap_conn_cfg . event_length = 320 ;
ble_cfg . conn_cfg . params . gap_conn_cfg . conn_count = BLE_GAP_CONN_COUNT_DEFAULT ;
err_code = sd_ble_cfg_set ( BLE_CONN_CFG_GAP , & ble_cfg , ram_start ) ;
APP_ERROR_CHECK ( err_code ) ;
// Enable BLE stack.
err_code = softdevice_enable ( & ram_start ) ;
APP_ERROR_CHECK ( err_code ) ;
// Subscribe for BLE events.
err_code = softdevice_ble_evt_handler_set ( ble_evt_dispatch ) ;
APP_ERROR_CHECK ( err_code ) ;
}
/**@brief Function for handling events from the GATT library. */
static void gatt_evt_handler ( nrf_ble_gatt_t * p_gatt , const nrf_ble_gatt_evt_t * p_evt )
{
if ( ( m_conn_handle = = p_evt - > conn_handle ) & & ( p_evt - > evt_id = = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED ) )
{
m_ble_nus_max_data_len = p_evt - > params . att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH ;
rt_kprintf ( " Data len is set to 0x%X(%d) \r \n " , m_ble_nus_max_data_len , m_ble_nus_max_data_len ) ;
}
rt_kprintf ( " ATT MTU exchange completed. central 0x%x peripheral 0x%x \r \n " , p_gatt - > att_mtu_desired_central , p_gatt - > att_mtu_desired_periph ) ;
}
/**@brief Function for initializing the GATT library. */
static void gatt_init ( void )
{
ret_code_t err_code ;
err_code = nrf_ble_gatt_init ( & m_gatt , gatt_evt_handler ) ;
APP_ERROR_CHECK ( err_code ) ;
err_code = nrf_ble_gatt_att_mtu_periph_set ( & m_gatt , 64 ) ;
APP_ERROR_CHECK ( err_code ) ;
}
/**@brief Function for initializing the Advertising functionality.
*/
static void advertising_init ( void )
{
uint32_t err_code ;
ble_advdata_t advdata ;
ble_advdata_t scanrsp ;
ble_adv_modes_config_t options ;
// Build advertising data struct to pass into @ref ble_advertising_init.
memset ( & advdata , 0 , sizeof ( advdata ) ) ;
advdata . name_type = BLE_ADVDATA_FULL_NAME ;
advdata . include_appearance = false ;
advdata . flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE ;
memset ( & scanrsp , 0 , sizeof ( scanrsp ) ) ;
scanrsp . uuids_complete . uuid_cnt = sizeof ( m_adv_uuids ) / sizeof ( m_adv_uuids [ 0 ] ) ;
scanrsp . uuids_complete . p_uuids = m_adv_uuids ;
memset ( & options , 0 , sizeof ( options ) ) ;
options . ble_adv_fast_enabled = true ;
options . ble_adv_fast_interval = APP_ADV_INTERVAL ;
options . ble_adv_fast_timeout = APP_ADV_TIMEOUT_IN_SECONDS ;
err_code = ble_advertising_init ( & advdata , & scanrsp , & options , on_adv_evt , NULL ) ;
APP_ERROR_CHECK ( err_code ) ;
ble_advertising_conn_cfg_tag_set ( CONN_CFG_TAG ) ;
}
/**@brief Function for handling app_uart events.
*
* @ details This function will receive a single character from the app_uart module and append it to
* a string . The string will be be sent over BLE when the last character received was a
* ' new line ' ' \ n ' ( hex 0x0A ) or if the string has reached the maximum data length .
*/
/**@snippet [Handling the data received over UART] */
void uart_event_handle ( rt_device_t uart )
{
uint8_t data_array [ BLE_NUS_MAX_DATA_LEN ] ;
rt_size_t size = 0 ;
uint32_t err_code ;
size = rt_device_read ( uart , 0 , data_array , BLE_NUS_MAX_DATA_LEN ) ;
if ( size < = 0 )
{
return ;
}
do
{
err_code = ble_nus_string_send ( & m_nus , data_array , size ) ;
if ( ( err_code ! = NRF_ERROR_INVALID_STATE ) & & ( err_code ! = NRF_ERROR_BUSY ) )
{
APP_ERROR_CHECK ( err_code ) ;
}
} while ( err_code = = NRF_ERROR_BUSY ) ;
}
/**@snippet [Handling the data received over UART] */
/**@brief Function for initializing the UART module.
*/
/**@snippet [UART Initialization] */
static rt_bool_t _stack_init ( void )
{
uint32_t err_code ;
stack_event = rt_event_create ( " stackev " , RT_IPC_FLAG_FIFO ) ;
sd_evt_sem = rt_sem_create ( " sdsem " , 0 , RT_IPC_FLAG_FIFO ) ;
stack_evt_mq = rt_mq_create ( " stackmq " , BLE_STACK_EVT_MSG_BUF_SIZE , STACK_EVT_MQ_NUM , RT_IPC_FLAG_FIFO ) ;
evt_sample = rt_malloc ( BLE_STACK_EVT_MSG_BUF_SIZE ) ;
if ( ! stack_event | | ! sd_evt_sem | | ! stack_evt_mq | | ! evt_sample )
{
rt_kprintf ( " uart rx sem create failure \n " ) ;
return RT_FALSE ;
}
// Initialize.
err_code = app_timer_init ( ) ;
APP_ERROR_CHECK ( err_code ) ;
ble_stack_init ( ) ;
gap_params_init ( ) ;
gatt_init ( ) ;
services_init ( ) ;
advertising_init ( ) ;
conn_params_init ( ) ;
return RT_TRUE ;
}
/**@brief Application main function.
*/
static void _stack_thread ( void * parameter )
{
rt_tick_t next_timeout = ( rt_tick_t ) RT_WAITING_FOREVER ;
2017-05-27 11:28:40 +08:00
2017-05-15 16:12:15 +08:00
FAST_ADV ( ) ;
// Enter main loop.
for ( ; ; )
{
rt_uint32_t event = 0 ;
rt_tick_t dispatch_timeout = RT_WAITING_NO ;
rt_event_recv ( stack_event , STACK_EV_DISCON | STACK_EV_DISPATCH | STACK_EV_KEY ,
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR , next_timeout , & event ) ;
if ( evt_dispatch_worker ( ) ! = RT_EOK )
{
dispatch_timeout = ( rt_tick_t ) RT_WAITING_FOREVER ;
}
if ( event & STACK_EV_DISCON )
{
if ( BLE_CONN_HANDLE_INVALID ! = m_conn_handle )
{
sd_ble_gap_disconnect ( m_conn_handle , BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION ) ;
}
}
if ( event & STACK_EV_KEY )
{
if ( stack_state ! = STACK_STATE_CON & & stack_state ! = STACK_STATE_ADV )
{
FAST_ADV ( ) ;
}
}
next_timeout = ( rt_tick_t ) RT_WAITING_FOREVER ;
if ( dispatch_timeout < next_timeout )
{
next_timeout = dispatch_timeout ;
}
}
}
static void _softdevice_thread ( void * parameter )
{
for ( ; ; )
{
rt_sem_take ( sd_evt_sem , RT_WAITING_FOREVER ) ;
intern_softdevice_events_execute ( ) ;
}
}
rt_err_t ble_init ( void )
{
rt_thread_t thread ;
_stack_init ( ) ;
thread = rt_thread_create ( " sdth " , _softdevice_thread , RT_NULL , 512 , 0 , 10 ) ;
if ( thread ! = RT_NULL )
{
rt_thread_startup ( thread ) ;
}
else
{
return RT_ERROR ;
}
thread = rt_thread_create ( " bleth " , _stack_thread , RT_NULL , 2048 , 1 , 10 ) ;
if ( thread ! = RT_NULL )
{
return rt_thread_startup ( thread ) ;
}
return RT_ERROR ;
}