Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b2f4529c3 | |||
| 1908ba34ff | |||
| bc46a7f70c | |||
| 94765fc0e8 | |||
| a865dea78b | |||
| a92ea7cc28 | |||
| 8ff9a297d5 | |||
| 6acd56bf8f |
+15
-4
@@ -152,11 +152,11 @@ 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.
|
||||
@@ -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.
|
||||
@@ -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_REGULAR_DATA_CHAR 0xFFF1
|
||||
#define BLE_UUID_LOW_FREQ_DATA_CHAR 0xFFF2
|
||||
#define BLE_UUID_AUXILIARY_DATA_CHAR 0xFFF3
|
||||
#define BLE_UUID_STATUS_CHAR 0xFFF4
|
||||
#define BLE_UUID_EVENT_CHAR 0xFFF5
|
||||
|
||||
#define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<ProjectFile>bmd380_central.vcxproj</ProjectFile>
|
||||
<RemoteBuildEnvironment>
|
||||
<Records />
|
||||
<EnvironmentSetupFiles />
|
||||
</RemoteBuildEnvironment>
|
||||
<ParallelJobCount>1</ParallelJobCount>
|
||||
<SuppressDirectoryChangeMessages>true</SuppressDirectoryChangeMessages>
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
<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>12.2.1/12.2/r2</ToolchainVersion>
|
||||
<MCUPropertyListFile>$(ProjectDir)nrf5x.props</MCUPropertyListFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
|
||||
<ToolchainID>com.visualgdb.arm-eabi</ToolchainID>
|
||||
<ToolchainVersion>10.3.1/10.2.90/r1</ToolchainVersion>
|
||||
<ToolchainVersion>12.2.1/12.2/r2</ToolchainVersion>
|
||||
<MCUPropertyListFile>$(ProjectDir)nrf5x.props</MCUPropertyListFile>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|VisualGDB'">
|
||||
@@ -55,7 +55,8 @@
|
||||
<LibrarySearchDirectories>%(Link.LibrarySearchDirectories)</LibrarySearchDirectories>
|
||||
<AdditionalLibraryNames>%(Link.AdditionalLibraryNames)</AdditionalLibraryNames>
|
||||
<AdditionalLinkerInputs>%(Link.AdditionalLinkerInputs)</AdditionalLinkerInputs>
|
||||
<AdditionalOptions />
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|VisualGDB'">
|
||||
@@ -77,6 +78,10 @@
|
||||
</ImportGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="host_tasks.c" />
|
||||
<ClCompile Include="le_gatt_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" />
|
||||
@@ -379,7 +384,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,15 +1667,24 @@
|
||||
<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>
|
||||
<ClCompile Include="host_tasks.c">
|
||||
<Filter>Source files</Filter>
|
||||
</ClCompile>
|
||||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\bmd380_sdk\components\ble\ble_services\ble_dis_c\ble_dis_c.h">
|
||||
|
||||
+162
-122
@@ -33,13 +33,13 @@ typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} host_cmd_survive_t;
|
||||
} ins_survive_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} host_cmd_scan_t;
|
||||
} ins_scan_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -47,28 +47,28 @@ typedef struct
|
||||
uint8_t len;
|
||||
uint8_t addr_type;
|
||||
uint8_t addr[6];
|
||||
} host_cmd_connect_t;
|
||||
} ins_connect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
} host_cmd_disconnect_t;
|
||||
} ins_disconnect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t handle;
|
||||
uint8_t write_date[0];
|
||||
} host_cmd_write_char_t;
|
||||
uint8_t write_data[255];
|
||||
} ins_write_char_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t len;
|
||||
uint8_t handle;
|
||||
} host_cmd_read_char_t;
|
||||
} ins_read_char_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
@@ -81,80 +81,127 @@ typedef union
|
||||
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;
|
||||
|
||||
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;
|
||||
#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
|
||||
|
||||
} host_command_t;
|
||||
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 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
|
||||
#define INST_SUFFIX 0xF1
|
||||
|
||||
static MessageBufferHandle_t host_cmd_msg;
|
||||
|
||||
static void survive_ack(void)
|
||||
static void success_ack(void)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x01, 0x03 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
|
||||
void on_survive(host_cmd_survive_t *p_cmd)
|
||||
static void on_ins_scan(ins_scan_t *p_ins)
|
||||
{
|
||||
survive_ack();
|
||||
extern void le_scan_start(void);
|
||||
le_scan_start();
|
||||
}
|
||||
|
||||
static void connect_ack(void)
|
||||
bool connect_start = false;
|
||||
static void on_ins_connect(ins_connect_t *p_ins)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x04, 0x2E, 0x50, 0x30, 0x04 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
}
|
||||
ble_gap_addr_t peer_addr;
|
||||
memset(&peer_addr, 0x00, sizeof(peer_addr));
|
||||
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];
|
||||
|
||||
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);
|
||||
le_scan_stop();
|
||||
|
||||
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());
|
||||
vTaskDelay(pdMS_TO_TICKS(5));
|
||||
|
||||
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)\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]);
|
||||
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 disconnect_ack(void)
|
||||
static void on_ins_write_char(ins_write_char_t *p_ins)
|
||||
{
|
||||
uint8_t ack[] = { 0x04, 0x00, 0x01, 0x03 };
|
||||
uart_drv_tx(ack, sizeof(ack));
|
||||
NRF_LOG_INFO("write handle: 0x%02X", p_ins->handle);
|
||||
uint16_t write_size = p_ins->len - sizeof(p_ins->handle) - 1;
|
||||
extern ret_code_t le_gatt_c_write_req(uint32_t handle, void *, uint16_t);
|
||||
ret_code_t ret_code = le_gatt_c_write_req(p_ins->handle, p_ins->write_data, write_size);
|
||||
if (ret_code == NRF_SUCCESS)
|
||||
{
|
||||
success_ack();
|
||||
}
|
||||
}
|
||||
|
||||
static void on_disconnect(host_cmd_disconnect_t *p_cmd)
|
||||
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_scan(host_cmd_scan_t *p_cmd)
|
||||
static void on_ins_survive(ins_survive_t *p_ins)
|
||||
{
|
||||
extern void le_scan_start(void);
|
||||
le_scan_start();
|
||||
success_ack();
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t rsp_code;
|
||||
union
|
||||
{
|
||||
uint8_t len;
|
||||
uint8_t payload[256];
|
||||
};
|
||||
} __PACKED read_char_rsp_t;
|
||||
|
||||
read_char_rsp_t read_char_rsp;
|
||||
void host_read_char_cb(uint8_t *p_data, uint16_t len)
|
||||
{
|
||||
read_char_rsp.rsp_code = 0x0004;
|
||||
memcpy(&read_char_rsp.len, p_data, len);
|
||||
uart_drv_tx(&read_char_rsp, offsetof(read_char_rsp_t, payload) + len);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
@@ -176,63 +223,43 @@ void host_scan_filter_match_cb(
|
||||
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];
|
||||
uint8_t manu_spec_data[15];
|
||||
uint8_t dev_name[21];
|
||||
} __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 },
|
||||
};
|
||||
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 };
|
||||
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);
|
||||
}
|
||||
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]);
|
||||
|
||||
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]",
|
||||
NRF_LOG_INFO("Found: %s [%s, %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);
|
||||
}
|
||||
|
||||
void host_connected_cb(void)
|
||||
{
|
||||
success_ack();
|
||||
}
|
||||
|
||||
static void host_cmd_exec_task(void *p_arg)
|
||||
@@ -240,26 +267,32 @@ static void host_cmd_exec_task(void *p_arg)
|
||||
for (;;)
|
||||
{
|
||||
static uint8_t buf[256] = { 0 };
|
||||
host_command_t *p_cmd = (void *)buf;
|
||||
host_ins_t *p_ins = (void *)buf;
|
||||
|
||||
p_cmd->raw.opcode = CMD_NULL;
|
||||
p_cmd->raw.len = 0;
|
||||
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_cmd->raw.opcode)
|
||||
switch (p_ins->raw.opcode)
|
||||
{
|
||||
case CMD_SURVIVE:
|
||||
on_survive(&p_cmd->survive);
|
||||
case INS_SCAN:
|
||||
on_ins_scan(&p_ins->scan);
|
||||
break;
|
||||
case CMD_CONNECT:
|
||||
on_connect(&p_cmd->connect);
|
||||
case INS_CONNECT:
|
||||
on_ins_connect(&p_ins->connect);
|
||||
break;
|
||||
case CMD_DISCONNECT:
|
||||
on_disconnect(&p_cmd->disconnect);
|
||||
case INS_WRITE_CHAR:
|
||||
on_ins_write_char(&p_ins->write_char);
|
||||
break;
|
||||
case CMD_SCAN:
|
||||
on_scan(&p_cmd->scan);
|
||||
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;
|
||||
@@ -278,29 +311,37 @@ static void host_cmd_recv_task(void *p_arg)
|
||||
|
||||
while (offset < recv)
|
||||
{
|
||||
host_command_t *p_cmd = (void *)&buf[offset];
|
||||
host_ins_t *p_ins = (void *)&buf[offset];
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
|
||||
if (p_cmd->raw.payload[p_cmd->raw.len] == CMD_SUFFIX)
|
||||
if (p_ins->raw.payload[p_ins->raw.len] == INST_SUFFIX)
|
||||
{
|
||||
switch (p_cmd->raw.opcode)
|
||||
switch (p_ins->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);
|
||||
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 CMD_CONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_cmd, sizeof(host_cmd_connect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(host_cmd_connect_t);
|
||||
case INS_CONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_connect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_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);
|
||||
case INS_DISCONNECT:
|
||||
xMessageBufferSend(host_cmd_msg, p_ins, sizeof(ins_disconnect_t), pdMS_TO_TICKS(0));
|
||||
offset += sizeof(ins_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);
|
||||
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++;
|
||||
@@ -322,10 +363,9 @@ static void host_tasks_handler(ble_evt_t const *p_ble_evt, void *p_context)
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
connect_ack();
|
||||
break;
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
disconnect_ack();
|
||||
success_ack();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
+4
-2
@@ -26,8 +26,8 @@ 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);
|
||||
break;
|
||||
case BLE_DB_DISCOVERY_ERROR:
|
||||
NRF_LOG_INFO("BLE_DB_DISCOVERY_ERROR");
|
||||
@@ -37,6 +37,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;
|
||||
|
||||
-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);
|
||||
}
|
||||
}
|
||||
@@ -31,13 +31,23 @@ void le_gap_init(const char *device_name, uint16_t usAppearance)
|
||||
// TODO...
|
||||
}
|
||||
|
||||
void le_gap_connet(ble_gap_addr_t *p_peer_addr, nrf_ble_scan_t *p_scan)
|
||||
void le_gap_connet(ble_gap_addr_t *p_peer_addr)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
+373
@@ -0,0 +1,373 @@
|
||||
#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
|
||||
|
||||
extern nrf_ble_gq_t *le_gap_queue(void);
|
||||
|
||||
struct ble_gatt_c_s
|
||||
{
|
||||
uint16_t conn_handle;
|
||||
void (*evt_handler)(ble_evt_t const *p_ble_evt, void *p_context);
|
||||
union
|
||||
{
|
||||
uint16_t char_handles[5];
|
||||
struct
|
||||
{
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
uint16_t handle_mapping[5];
|
||||
|
||||
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;
|
||||
p_ble_gatt_c->regular_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_ble_gatt_c->auxiliary_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_ble_gatt_c->status_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_ble_gatt_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_gatt_c_t *p_ble_gatt_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
hvx_cnt = 0;
|
||||
hvx_begin = 0;
|
||||
}
|
||||
|
||||
static void on_hvx(ble_gatt_c_t *p_ble_gatt_c, ble_evt_t const *p_ble_evt)
|
||||
{
|
||||
uint32_t len = p_ble_evt->evt.gattc_evt.params.hvx.len;
|
||||
uint8_t *p = p_ble_evt->evt.gattc_evt.params.hvx.data;
|
||||
NRF_LOG_INFO("=======================================");
|
||||
NRF_LOG_HEXDUMP_INFO(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));
|
||||
le_gatt_ccdc_configure(m_gatt_c.conn_handle, m_gatt_c.regular_data_char_handle, true);
|
||||
le_gatt_ccdc_configure(m_gatt_c.conn_handle, m_gatt_c.low_freq_data_char_handle, true);
|
||||
le_gatt_ccdc_configure(m_gatt_c.conn_handle, m_gatt_c.auxiliary_data_char_handle, true);
|
||||
le_gatt_ccdc_configure(m_gatt_c.conn_handle, m_gatt_c.status_char_handle, true);
|
||||
le_gatt_ccdc_configure(m_gatt_c.conn_handle, m_gatt_c.event_char_handle, 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;
|
||||
m_gatt_c.regular_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
m_gatt_c.auxiliary_data_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
m_gatt_c.status_char_handle = BLE_GATT_HANDLE_INVALID;
|
||||
m_gatt_c.event_char_handle = 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 (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
|
||||
{
|
||||
switch (p_chars[i].characteristic.uuid.uuid)
|
||||
{
|
||||
case BLE_UUID_REGULAR_DATA_CHAR:
|
||||
m_gatt_c.regular_data_char_handle = p_chars[i].characteristic.handle_value;
|
||||
handle_mapping[0] = m_gatt_c.regular_data_char_handle;
|
||||
break;
|
||||
case BLE_UUID_LOW_FREQ_DATA_CHAR:
|
||||
m_gatt_c.low_freq_data_char_handle = p_chars[i].characteristic.handle_value;
|
||||
handle_mapping[1] = m_gatt_c.low_freq_data_char_handle;
|
||||
break;
|
||||
case BLE_UUID_AUXILIARY_DATA_CHAR:
|
||||
m_gatt_c.auxiliary_data_char_handle = p_chars[i].characteristic.handle_value;
|
||||
handle_mapping[2] = m_gatt_c.auxiliary_data_char_handle;
|
||||
break;
|
||||
case BLE_UUID_STATUS_CHAR:
|
||||
m_gatt_c.status_char_handle = p_chars[i].characteristic.handle_value;
|
||||
handle_mapping[3] = m_gatt_c.status_char_handle;
|
||||
break;
|
||||
case BLE_UUID_EVENT_CHAR:
|
||||
m_gatt_c.event_char_handle = p_chars[i].characteristic.handle_value;
|
||||
handle_mapping[4] = m_gatt_c.event_char_handle;
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
@@ -22,14 +22,13 @@ extern "C"
|
||||
#include "nrf_sdh_freertos.h"
|
||||
|
||||
#include "ble_advdata.h"
|
||||
#include "ble_gap.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)
|
||||
@@ -41,16 +40,6 @@ static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
|
||||
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,
|
||||
@@ -61,6 +50,17 @@ static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
|
||||
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,
|
||||
@@ -68,6 +68,7 @@ static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
|
||||
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,
|
||||
@@ -77,86 +78,82 @@ static void on_adv_report(ble_gap_evt_adv_report_t const *p_adv_report)
|
||||
p_adv_report->rssi);
|
||||
}
|
||||
|
||||
static void scan_evt_handler(scan_evt_t const *p_scan_evt)
|
||||
|
||||
|
||||
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;
|
||||
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));
|
||||
|
||||
switch (p_scan_evt->scan_evt_id)
|
||||
if (ble_advdata_uuid_find(p_adv_report->data.p_data, data_len, &filter_uuid))
|
||||
{
|
||||
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);
|
||||
mac = u64_peer_addr;
|
||||
|
||||
char peer_addr_str[(2 + 1) * BLE_GAP_ADDR_LEN + 1] = { 0 };
|
||||
|
||||
if (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]);
|
||||
}
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static char const *m_target_periph_name[] = ELITE_DEVICE_NAME_LIST;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
// TODO...
|
||||
}
|
||||
|
||||
bool is_scanning = false;
|
||||
|
||||
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);
|
||||
if (is_scanning != true)
|
||||
{
|
||||
NRF_LOG_INFO("Start scanning for UUID service 0x%04X.",
|
||||
BLE_UUID_CUSTOM_SERVICE);
|
||||
is_scanning = true;
|
||||
sd_ble_gap_scan_start(&scan_params, &adv_report_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void le_scan_stop(void)
|
||||
{
|
||||
NRF_LOG_INFO("Stop scanning.");
|
||||
nrf_ble_scan_stop();
|
||||
sd_ble_gap_scan_stop();
|
||||
is_scanning = false;
|
||||
}
|
||||
|
||||
const nrf_ble_scan_t *le_scan_obj(void)
|
||||
ble_gap_scan_params_t *le_scan_params(void)
|
||||
{
|
||||
return &m_scan;
|
||||
}
|
||||
return &scan_params;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -99,19 +102,96 @@ static void le_stack_Init(void)
|
||||
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, le_evt_handler, NULL);
|
||||
}
|
||||
|
||||
|
||||
#define ROY_MEM_SEL NRF_GPIO_PIN_MAP(1, 9)
|
||||
#define ROY_MEM_BZY NRF_GPIO_PIN_MAP(0, 8)
|
||||
#define ROY_MEM_REQ NRF_GPIO_PIN_MAP(0, 6)
|
||||
#define ROY_RAM_SEL NRF_GPIO_PIN_MAP(0, 5)
|
||||
#define ROY_MEM_TEST_01 NRF_GPIO_PIN_MAP(0, 26)
|
||||
#define ROY_MEM_TEST_02 NRF_GPIO_PIN_MAP(0, 17)
|
||||
#define ROY_MEM_TEST_03 NRF_GPIO_PIN_MAP(0, 21)
|
||||
#define ROY_MEM_TEST_04 NRF_GPIO_PIN_MAP(0, 19)
|
||||
#define ROY_MEM_TEST_05 NRF_GPIO_PIN_MAP(0, 22)
|
||||
#define ROY_LED1 NRF_GPIO_PIN_MAP(1, 10)
|
||||
|
||||
static void mem_pin(void *p_arg)
|
||||
{
|
||||
nrf_gpio_cfg_output(ROY_MEM_SEL);
|
||||
nrf_gpio_cfg_output(ROY_MEM_BZY);
|
||||
nrf_gpio_cfg_output(ROY_MEM_REQ);
|
||||
nrf_gpio_cfg_output(ROY_RAM_SEL);
|
||||
|
||||
static uint8_t time = 0;
|
||||
for (;;) {
|
||||
|
||||
NRF_LOG_INFO("mem_pin %d", time);
|
||||
time++;
|
||||
nrf_gpio_pin_set(ROY_MEM_SEL);
|
||||
nrf_gpio_pin_set(ROY_MEM_BZY);
|
||||
nrf_gpio_pin_set(ROY_MEM_REQ);
|
||||
nrf_gpio_pin_set(ROY_RAM_SEL);
|
||||
NRF_LOG_INFO("mem_pin on");
|
||||
nrf_delay_ms(2000);
|
||||
|
||||
nrf_gpio_pin_clear(ROY_MEM_SEL);
|
||||
nrf_gpio_pin_clear(ROY_MEM_BZY);
|
||||
nrf_gpio_pin_clear(ROY_MEM_REQ);
|
||||
nrf_gpio_pin_clear(ROY_RAM_SEL);
|
||||
NRF_LOG_INFO("mem_pin off");
|
||||
nrf_delay_ms(2000);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_pin(void *p_arg)
|
||||
{
|
||||
nrf_gpio_cfg_output(ROY_MEM_TEST_01);
|
||||
nrf_gpio_cfg_output(ROY_MEM_TEST_02);
|
||||
nrf_gpio_cfg_output(ROY_MEM_TEST_03);
|
||||
nrf_gpio_cfg_output(ROY_MEM_TEST_04);
|
||||
nrf_gpio_cfg_output(ROY_MEM_TEST_05);
|
||||
nrf_gpio_cfg_output(ROY_LED1);
|
||||
|
||||
static uint8_t time = 0;
|
||||
for (;;) {
|
||||
|
||||
NRF_LOG_INFO("test_pin %d", time);
|
||||
time++;
|
||||
nrf_gpio_pin_set(ROY_MEM_TEST_01);
|
||||
nrf_gpio_pin_set(ROY_MEM_TEST_02);
|
||||
nrf_gpio_pin_set(ROY_MEM_TEST_03);
|
||||
nrf_gpio_pin_set(ROY_MEM_TEST_04);
|
||||
nrf_gpio_pin_set(ROY_MEM_TEST_05);
|
||||
nrf_gpio_pin_set(ROY_LED1);
|
||||
NRF_LOG_INFO("test_pin on");
|
||||
nrf_delay_ms(1000);
|
||||
|
||||
nrf_gpio_pin_clear(ROY_MEM_TEST_01);
|
||||
nrf_gpio_pin_clear(ROY_MEM_TEST_02);
|
||||
nrf_gpio_pin_clear(ROY_MEM_TEST_03);
|
||||
nrf_gpio_pin_clear(ROY_MEM_TEST_04);
|
||||
nrf_gpio_pin_clear(ROY_MEM_TEST_05);
|
||||
nrf_gpio_pin_clear(ROY_LED1);
|
||||
NRF_LOG_INFO("test_pin off");
|
||||
nrf_delay_ms(1000);
|
||||
}
|
||||
}
|
||||
|
||||
static void initialize(void *p_context)
|
||||
{
|
||||
extern void uart_drv_init(void);
|
||||
uart_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_gap_init(void);
|
||||
le_gap_init();
|
||||
@@ -136,6 +216,9 @@ int main(void)
|
||||
|
||||
nrf_sdh_freertos_init(initialize, NULL);
|
||||
|
||||
//xTaskCreate(mem_pin, "mem_pin", 512, NULL, 5, NULL);
|
||||
//xTaskCreate(test_pin, "test_pin", 512, NULL, 5, NULL);
|
||||
|
||||
vTaskStartScheduler();
|
||||
|
||||
for (;;)
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_gpiote.h"
|
||||
#include "nrf_spim.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.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_REQ_GPIOTE_ID 0
|
||||
|
||||
static int ram_sel_signal = 0;
|
||||
|
||||
static SemaphoreHandle_t mem_drv_semphr = NULL;
|
||||
static TaskHandle_t mem_drv_task_handle = NULL;
|
||||
|
||||
void mem_ram_select(int select)
|
||||
{
|
||||
ram_sel_signal = select;
|
||||
switch (ram_sel_signal)
|
||||
{
|
||||
case 0:
|
||||
nrf_gpio_pin_clear(RAM_SEL_PIN);
|
||||
break;
|
||||
case 1:
|
||||
nrf_gpio_pin_set(RAM_SEL_PIN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mem_drv_task(void *p_arg)
|
||||
{
|
||||
static uint32_t sel = 0;
|
||||
|
||||
extern void sram_drv_init(void);
|
||||
sram_drv_init();
|
||||
|
||||
extern void sram_drv_reset(void);
|
||||
extern int sram_drv_write(uint32_t addr, void *p_dest, uint32_t len);
|
||||
NRF_LOG_INFO("build----1")
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
sel ^= 1;
|
||||
mem_ram_select(sel);
|
||||
sram_drv_reset();
|
||||
|
||||
if (sel) {
|
||||
uint8_t buf_1[12] = {1,2,2,6,5,6,7,8,9,0};
|
||||
sram_drv_write(0x0000, buf_1, sizeof(buf_1));
|
||||
} else {
|
||||
uint8_t buf_0[12] = {9,9,8,8,7,7,6,6,5,5,0};
|
||||
sram_drv_write(0x0000, buf_0, sizeof(buf_0));
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
extern int sram_drv_read(uint32_t addr, void *p_dest, uint32_t len);
|
||||
|
||||
uint8_t buf[4];
|
||||
|
||||
xSemaphoreTake(mem_drv_semphr, portMAX_DELAY);
|
||||
|
||||
sel ^= 0x01;
|
||||
mem_ram_select(sel);
|
||||
sram_drv_read(0x0000, buf, sizeof(buf));
|
||||
NRF_LOG_INFO("mem_sel[%d]: 0x%02X, 0x%02X, 0x%02X, 0x%02X", sel, buf[0], buf[1], buf[2], buf[3]);
|
||||
}
|
||||
}
|
||||
|
||||
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_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_drv_semphr = xSemaphoreCreateBinary();
|
||||
xTaskCreate(mem_drv_task, "mem_drv", 256, NULL, 5, NULL);
|
||||
|
||||
sd_nvic_SetPriority(GPIOTE_IRQn, _PRIO_APP_HIGH);
|
||||
sd_nvic_EnableIRQ(GPIOTE_IRQn);
|
||||
}
|
||||
|
||||
static void mem_req_int_callback(void)
|
||||
{
|
||||
uint32_t mem_sel = nrf_gpio_pin_read(MEM_SEL_PIN);
|
||||
uint32_t mem_req = nrf_gpio_pin_read(MEM_REQ_PIN);
|
||||
if (mem_sel != mem_req)
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
xSemaphoreGiveFromISR(mem_drv_semphr, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
|
||||
void GPIOTE_IRQHandler(void)
|
||||
{
|
||||
if (NRF_GPIOTE->EVENTS_IN[MEM_REQ_GPIOTE_ID])
|
||||
{
|
||||
NRF_GPIOTE->EVENTS_IN[MEM_REQ_GPIOTE_ID] = 0;
|
||||
mem_req_int_callback();
|
||||
}
|
||||
}
|
||||
+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>12.2.1</GCC>
|
||||
<GDB>12.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)
|
||||
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_spim.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define SRAM_23K640 0
|
||||
#define SRAM_23K256
|
||||
|
||||
#define SRAM_DEVICE SRAM_23K640
|
||||
#define SRAM_BANK_NUM 2
|
||||
#define READ_CMD (0b00000011)
|
||||
#define WRITE_CMD (0b00000010)
|
||||
#define READ_STATUS_CMD (0b00000101)
|
||||
#define WRITE_STATUS_CMD (0b00000001)
|
||||
|
||||
#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)
|
||||
#elif (SRAM_DEVICE == SRAM_23K256)
|
||||
#define SRAM_SIZE (256 * 1024 / 8)
|
||||
#else
|
||||
#error "unvalid external sram device"
|
||||
#endif
|
||||
|
||||
#define SRAM_SPIM (NRF_SPIM3)
|
||||
#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;
|
||||
|
||||
static void write_bytes(void *p, uint32_t len)
|
||||
{
|
||||
nrf_spim_tx_buffer_set(SRAM_SPIM, p, len);
|
||||
nrf_spim_rx_buffer_set(SRAM_SPIM, p, 0);
|
||||
nrf_spim_task_trigger(SRAM_SPIM, NRF_SPIM_TASK_START);
|
||||
xSemaphoreTake(txrx_end_sem, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void read_bytes(void *p, uint32_t len)
|
||||
{
|
||||
nrf_spim_tx_buffer_set(SRAM_SPIM, p, 0);
|
||||
nrf_spim_rx_buffer_set(SRAM_SPIM, p, len);
|
||||
nrf_spim_task_trigger(SRAM_SPIM, NRF_SPIM_TASK_START);
|
||||
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[] = {
|
||||
WRITE_STATUS_CMD, 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[] = {
|
||||
inst,
|
||||
(addr & 0x0000FF00) >> 0x08,
|
||||
(addr & 0x000000FF) >> 0x00
|
||||
};
|
||||
write_bytes(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
void sram_drv_write_status(uint8_t mode)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
nrf_gpio_pin_clear(CS_PIN);
|
||||
write_status(mode | HOLD_DISABLE);
|
||||
nrf_gpio_pin_set(CS_PIN);
|
||||
xSemaphoreGive(sram_mutex);
|
||||
}
|
||||
|
||||
void sram_drv_read_status(uint8_t *mode)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
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_PIN);
|
||||
xSemaphoreGive(sram_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sram_drv_read(uint32_t addr, void *p_dest, uint32_t len)
|
||||
{
|
||||
xSemaphoreTake(sram_mutex, portMAX_DELAY);
|
||||
nrf_gpio_pin_clear(CS_PIN);
|
||||
write_inst_addr(READ_CMD, addr);
|
||||
read_bytes(p_dest, len);
|
||||
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();
|
||||
sram_mutex = xSemaphoreCreateMutex();
|
||||
// Config SPI mosi pin
|
||||
nrf_gpio_cfg_output(MOSI_PIN);
|
||||
nrf_gpio_pin_clear(MOSI_PIN);
|
||||
// Config SPI miso pin
|
||||
nrf_gpio_cfg_input(MISO_PIN, NRF_GPIO_PIN_PULLDOWN);
|
||||
// Config SPI clk pin
|
||||
nrf_gpio_cfg_output(SCLK_PIN);
|
||||
nrf_gpio_pin_clear(SCLK_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);
|
||||
nrf_spim_frequency_set(SRAM_SPIM, NRF_SPIM_FREQ_16M);
|
||||
nrf_spim_pins_set(SRAM_SPIM, SCLK_PIN, MOSI_PIN, MISO_PIN);
|
||||
nrf_spim_orc_set(SRAM_SPIM, 0x00);
|
||||
|
||||
// Enable SPI module
|
||||
nrf_spim_enable(SRAM_SPIM);
|
||||
|
||||
// Enable interrput (for easyDMA)
|
||||
sd_nvic_SetPriority(SPIM3_IRQn, _PRIO_APP_MID);
|
||||
sd_nvic_EnableIRQ(SPIM3_IRQn);
|
||||
nrf_spim_int_enable(SRAM_SPIM, NRF_SPIM_INT_END_MASK);
|
||||
}
|
||||
|
||||
void SPIM3_IRQHandler(void)
|
||||
{
|
||||
if (nrf_spim_int_enable_check(SRAM_SPIM, NRF_SPIM_INT_END_MASK))
|
||||
{
|
||||
nrf_spim_event_clear(SRAM_SPIM, NRF_SPIM_EVENT_END);
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
xSemaphoreGiveFromISR(txrx_end_sem, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
+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;
|
||||
}
|
||||
+6
-6
@@ -21,8 +21,8 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#define HOST_UART (NRF_UARTE0)
|
||||
#define HOST_uart_drv_tx_PIN 6
|
||||
#define HOST_UART_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;
|
||||
@@ -73,11 +73,11 @@ void uart_drv_init(void)
|
||||
uart_drv_rx_mutex = xSemaphoreCreateMutex();
|
||||
uart_drv_tx_mutex = xSemaphoreCreateMutex();
|
||||
|
||||
nrf_gpio_cfg_output(HOST_uart_drv_tx_PIN);
|
||||
nrf_gpio_cfg_input(HOST_UART_RX_PIN, NRF_GPIO_PIN_NOPULL);
|
||||
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_txrx_pins_set(HOST_UART, HOST_uart_drv_tx_PIN, HOST_UART_RX_PIN);
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user