From be584e29005247c83fb85a636b9ec8d3bfd95ee5 Mon Sep 17 00:00:00 2001 From: chain40 Date: Fri, 11 Aug 2023 08:52:49 +0800 Subject: [PATCH] cc2650_compitable --- app_config.h | 23 +- bmd380_central-Debug.vgdbsettings | 3 +- bmd380_central.vcxproj | 11 +- bmd380_central.vcxproj.filters | 12 +- host_tasks.c | 285 +++++++++++++---------- le_db_discovery.c | 6 +- le_eis_c.c | 303 ------------------------ le_gap.c | 47 +++- le_gatt_c.c | 375 ++++++++++++++++++++++++++++++ le_scan.c | 141 ++++++----- main.c | 23 +- mem_drv.c | 290 +++++++++++++++++++++++ nrf5x.props | 2 +- nrf5x.xml | 6 +- scripts/host_cmd.py | 67 ++++-- sram_drv.c | 94 +++++--- syscalls.c | 155 ++++++++++++ uart_drv.c | 6 +- 18 files changed, 1265 insertions(+), 584 deletions(-) delete mode 100644 le_eis_c.c create mode 100644 le_gatt_c.c create mode 100644 mem_drv.c create mode 100644 syscalls.c diff --git a/app_config.h b/app_config.h index 98be0a4..46fadb9 100644 --- a/app_config.h +++ b/app_config.h @@ -15,9 +15,9 @@ extern "C" #define NRF_LOG_BACKEND_UART_ENABLED 0 #define NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS 1 #define NRF_LOG_BACKEND_RTT_TX_RETRY_CNT 3 -#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64 +#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 256 #define NRF_LOG_DEFERRED 0 -#define NRF_LOG_USES_TIMESTAMP 0 +#define NRF_LOG_USES_TIMESTAMP 1 #define NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 0 // SEGGER-RTT @@ -152,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 diff --git a/bmd380_central-Debug.vgdbsettings b/bmd380_central-Debug.vgdbsettings index 7e6ce67..984c5c6 100644 --- a/bmd380_central-Debug.vgdbsettings +++ b/bmd380_central-Debug.vgdbsettings @@ -25,6 +25,7 @@ bmd380_central.vcxproj + 1 true @@ -129,7 +130,7 @@ _estack 0 false - + 2779096485 true \ No newline at end of file diff --git a/bmd380_central.vcxproj b/bmd380_central.vcxproj index 3e27aea..2a18caf 100644 --- a/bmd380_central.vcxproj +++ b/bmd380_central.vcxproj @@ -32,12 +32,12 @@ Debug com.visualgdb.arm-eabi - 10.3.1/10.2.90/r1 + 12.2.1/12.2/r2 $(ProjectDir)nrf5x.props com.visualgdb.arm-eabi - 10.3.1/10.2.90/r1 + 12.2.1/12.2/r2 $(ProjectDir)nrf5x.props @@ -55,7 +55,8 @@ %(Link.LibrarySearchDirectories) %(Link.AdditionalLibraryNames) %(Link.AdditionalLinkerInputs) - + + @@ -77,7 +78,10 @@ + + + @@ -380,7 +384,6 @@ - diff --git a/bmd380_central.vcxproj.filters b/bmd380_central.vcxproj.filters index 1ba2644..d7aa174 100644 --- a/bmd380_central.vcxproj.filters +++ b/bmd380_central.vcxproj.filters @@ -1667,9 +1667,6 @@ Source files - - Source files - Source files @@ -1679,6 +1676,15 @@ Source files + + Source files + + + Source files + + + Source files + diff --git a/host_tasks.c b/host_tasks.c index 40b0556..93756ef 100644 --- a/host_tasks.c +++ b/host_tasks.c @@ -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,126 @@ 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) +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 +222,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 +266,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 +310,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 +362,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; @@ -336,7 +375,7 @@ void host_tasks_init(void) { host_cmd_msg = xMessageBufferCreate(1024); xTaskCreate(host_cmd_recv_task, "cmd_recv", 128, NULL, 5, NULL); - xTaskCreate(host_cmd_exec_task, "cmd_exec", 512, NULL, 2, NULL); + xTaskCreate(host_cmd_exec_task, "cmd_exec", 512, NULL, 3, NULL); // Register a handler for BLE events. NRF_SDH_BLE_OBSERVER(m_tasks_observer, 3, host_tasks_handler, NULL); } diff --git a/le_db_discovery.c b/le_db_discovery.c index 6681667..7f45723 100644 --- a/le_db_discovery.c +++ b/le_db_discovery.c @@ -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; diff --git a/le_eis_c.c b/le_eis_c.c deleted file mode 100644 index 50352f1..0000000 --- a/le_eis_c.c +++ /dev/null @@ -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); - } -} diff --git a/le_gap.c b/le_gap.c index f8b09fd..b960676 100644 --- a/le_gap.c +++ b/le_gap.c @@ -26,18 +26,48 @@ extern "C" } #endif -void le_gap_init(const char *device_name, uint16_t usAppearance) +bool is_connected = false; + +static void le_gap_handler(ble_evt_t const *p_ble_evt, void *p_context) { - // TODO... + ret_code_t err_code; + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + is_connected = true; + break; + case BLE_GAP_EVT_DISCONNECTED: + is_connected = false; + break; + default: + break; + } } -void le_gap_connet(ble_gap_addr_t *p_peer_addr, nrf_ble_scan_t *p_scan) +void le_gap_init(const char *device_name, uint16_t usAppearance) +{ + + // Register a handler for BLE events. + NRF_SDH_BLE_OBSERVER(m_gap_observer, 3, le_gap_handler, NULL); +} + +void le_gap_connet(ble_gap_addr_t *p_peer_addr) { // If 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); } @@ -70,3 +100,8 @@ void le_gap_conn_param_update(uint16_t conn_handle) }; sd_ble_gap_conn_param_update(conn_handle, &gap_conn_params); } + +bool le_gap_is_connected(void) +{ + return is_connected; +} diff --git a/le_gatt_c.c b/le_gatt_c.c new file mode 100644 index 0000000..88f35ff --- /dev/null +++ b/le_gatt_c.c @@ -0,0 +1,375 @@ +#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; + extern void mem_board_reset(void); + mem_board_reset(); +} + +static void on_hvx(ble_gatt_c_t *p_ble_gatt_c, ble_evt_t const *p_ble_evt) +{ + uint32_t len = p_ble_evt->evt.gattc_evt.params.hvx.len; + uint8_t *p = (uint8_t *)p_ble_evt->evt.gattc_evt.params.hvx.data; + extern void mem_notify_cb(uint8_t *p, uint32_t len); + mem_notify_cb(p, len); +} + +static void on_read_rsp(ble_gatt_c_t *p_le_gatt_c, ble_evt_t const *p_ble_evt) +{ + extern void host_read_char_cb(uint8_t * p_data, uint16_t len); + uint16_t handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle; + + for (int i = 0; i < COUNTOF(p_le_gatt_c->char_handles); i++) + { + if (handle_mapping[i] == handle) + { + ble_gattc_evt_read_rsp_t const *p_response = &p_ble_evt->evt.gattc_evt.params.read_rsp; + host_read_char_cb((uint8_t *)p_response->data, p_response->len); + break; + } + } +} + +ret_code_t le_gatt_ccdc_configure(uint16_t conn_handle, uint16_t char_handle, bool notification_enable) +{ + if (conn_handle == BLE_CONN_HANDLE_INVALID) + { + __BKPT(255); + return NRF_ERROR_INVALID_PARAM; + } + + if (char_handle == BLE_GATT_HANDLE_INVALID) + { + __BKPT(255); + return NRF_ERROR_INVALID_PARAM; + } + + NRF_LOG_INFO("Configuring CCCD Handle = 0x%04X, Connection Handle = 0x%04X", + char_handle + 1, + conn_handle); + + nrf_ble_gq_req_t cccd_req; + uint16_t cccd_val = notification_enable ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INVALID; + uint8_t cccd[BLE_CCCD_VALUE_LEN]; + + cccd[0] = LSB_16(cccd_val); + cccd[1] = MSB_16(cccd_val); + + memset(&cccd_req, 0, sizeof(nrf_ble_gq_req_t)); + + cccd_req.type = NRF_BLE_GQ_REQ_GATTC_WRITE; + cccd_req.params.gattc_write.handle = char_handle + 1; + cccd_req.params.gattc_write.len = BLE_CCCD_VALUE_LEN; + cccd_req.params.gattc_write.offset = 0; + cccd_req.params.gattc_write.p_value = cccd; + cccd_req.params.gattc_write.write_op = BLE_GATT_OP_WRITE_REQ; + + return nrf_ble_gq_item_add(le_gap_queue(), &cccd_req, conn_handle); +} + +static void le_gatt_c_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) +{ + ble_gatt_c_t *p_ble_gatt_c = (ble_gatt_c_t *)p_context; + + if ((p_ble_gatt_c == NULL) || (p_ble_evt == NULL)) + { + return; + } + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_DISCONNECTED: + on_disconnected(p_ble_gatt_c, p_ble_evt); + break; + case BLE_GAP_EVT_CONNECTED: + on_connected(p_ble_gatt_c, p_ble_evt); + break; + case BLE_GATTC_EVT_HVX: + /* + Handle Value Notification or Indication event. + Confirm indication with @ref sd_ble_gattc_hv_confirm. + See @ref ble_gattc_evt_hvx_t. */ + on_hvx(p_ble_gatt_c, p_ble_evt); + break; + + case BLE_GATTC_EVT_READ_RSP: + /* + Read Response event. + See @ref ble_gattc_evt_read_rsp_t. */ + on_read_rsp(p_ble_gatt_c, p_ble_evt); + break; + + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + /* + Primary Service Discovery Response event. + See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */ + break; + case BLE_GATTC_EVT_REL_DISC_RSP: + /* + Relationship Discovery Response event. + See @ref ble_gattc_evt_rel_disc_rsp_t. */ + __BKPT(255); + break; + case BLE_GATTC_EVT_CHAR_DISC_RSP: + /* + Characteristic Discovery Response event. + See @ref ble_gattc_evt_char_disc_rsp_t. */ + break; + case BLE_GATTC_EVT_DESC_DISC_RSP: + /* + Descriptor Discovery Response event. + See @ref ble_gattc_evt_desc_disc_rsp_t. */ + break; + case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP: + /* + Attribute Information Response event. + See @ref ble_gattc_evt_attr_info_disc_rsp_t. */ + __BKPT(255); + break; + case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP: + /* + Read By UUID Response event. + See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */ + __BKPT(255); + break; + case BLE_GATTC_EVT_CHAR_VALS_READ_RSP: + /* + Read multiple Response event. + See @ref ble_gattc_evt_char_vals_read_rsp_t. */ + __BKPT(255); + break; + case BLE_GATTC_EVT_WRITE_RSP: + /* + Write Response event. + See @ref ble_gattc_evt_write_rsp_t. */ + break; + case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: + /* + Exchange MTU Response event. + See @ref ble_gattc_evt_exchange_mtu_rsp_t. */ + break; + case BLE_GATTC_EVT_TIMEOUT: + /* + Timeout event. + See @ref ble_gattc_evt_timeout_t. */ + __BKPT(255); + break; + case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: + /* + Write without Response transmission complete. */ + __BKPT(255); + break; + default: + // No implementation needed. + break; + } +} + +void le_gatt_c_cccd_timer_cb(TimerHandle_t xTimer) +{ + xTimerStop(xTimer, pdMS_TO_TICKS(0)); + 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; +} diff --git a/le_scan.c b/le_scan.c index 75c45bd..691973c 100644 --- a/le_scan.c +++ b/le_scan.c @@ -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; +} \ No newline at end of file diff --git a/main.c b/main.c index 27e4327..5cf16d6 100644 --- a/main.c +++ b/main.c @@ -40,8 +40,11 @@ static void le_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) ret_code_t err_code; switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_ADV_REPORT: - break; + case BLE_GAP_EVT_ADV_REPORT: { + extern void le_scan_handler(ble_evt_t const *p_ble_evt, void *p_context); + le_scan_handler(p_ble_evt, p_context); + } + break; case BLE_GAP_EVT_PHY_UPDATE: NRF_LOG_INFO("PHY update procedure is complete."); break; @@ -50,7 +53,6 @@ static void le_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) break; case BLE_GAP_EVT_CONNECTED: NRF_LOG_INFO("Connected to peer."); - le_scan_stop(); le_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle); le_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle); le_db_discovery_start(p_ble_evt->evt.gap_evt.conn_handle); @@ -62,7 +64,8 @@ static void le_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) le_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle); break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: { - ret_code_t err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); + ret_code_t err_code = sd_ble_gatts_sys_attr_set( + p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); APP_ERROR_CHECK(err_code); } break; @@ -104,17 +107,17 @@ static void initialize(void *p_context) extern void uart_drv_init(void); uart_drv_init(); - extern void sram_drv_init(void); - sram_drv_init(); - + extern void mem_board_init(void); + mem_board_init(); + extern void le_db_discovery_init(void); le_db_discovery_init(); extern void le_dis_c_init(void); le_dis_c_init(); - extern void le_eis_c_init(void); - le_eis_c_init(); + extern void le_gatt_c_init(void); + le_gatt_c_init(); extern void le_gap_init(void); le_gap_init(); @@ -131,7 +134,7 @@ static void initialize(void *p_context) int main(void) { - NRF_LOG_INIT(NULL, 0); + NRF_LOG_INIT(xTaskGetTickCount, configTICK_RATE_HZ); NRF_LOG_DEFAULT_BACKENDS_INIT(); NRF_LOG_INFO("%s Build: %s %s", LE_DEVICE_NAME, __TIME__, __DATE__); diff --git a/mem_drv.c b/mem_drv.c new file mode 100644 index 0000000..4a15802 --- /dev/null +++ b/mem_drv.c @@ -0,0 +1,290 @@ +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "nrf_gpio.h" +#include "nrf_gpiote.h" +#include "nrf_spim.h" + +#include "FreeRTOS.h" +#include "message_buffer.h" +#include "semphr.h" +#include "stream_buffer.h" +#include "task.h" + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" + +#ifdef __cplusplus +} +#endif + +#define MEM_SEL_PIN NRF_GPIO_PIN_MAP(1, 9) +#define MEM_BZY_PIN NRF_GPIO_PIN_MAP(0, 8) +#define MEM_REQ_PIN NRF_GPIO_PIN_MAP(0, 6) + +#define RAM_SEL_PIN NRF_GPIO_PIN_MAP(0, 5) + +#define MEM_TEST_01_PIN NRF_GPIO_PIN_MAP(0, 26) +#define MEM_TEST_02_PIN NRF_GPIO_PIN_MAP(0, 17) +#define MEM_TEST_03_PIN NRF_GPIO_PIN_MAP(0, 21) +#define MEM_TEST_04_PIN NRF_GPIO_PIN_MAP(0, 19) +#define MEM_TEST_05_PIN NRF_GPIO_PIN_MAP(0, 22) + +#define MEM_SEL_GPIOTE_ID 0 +#define MEM_REQ_GPIOTE_ID 1 + +#define MEM_DATA_UNIT 40 + +#define MEM_DUMP 0 + +static int ram_sel = 0; + +static SemaphoreHandle_t mem_sel_semphr = NULL; +static TaskHandle_t mem_drv_task_handle = NULL; +static StreamBufferHandle_t mem_drv_stream = NULL; + +typedef struct +{ + struct + { + union + { + uint32_t val; + struct + { + uint16_t len; + uint16_t marker; + } __PACKED; + } header[3]; + } green_frame; + uint8_t red_frame[2048]; +} mem_data_t; +mem_data_t mem_data; +uint32_t mem_notify_cnt = 0; +uint32_t mem_available_cnt = 0; +uint32_t mem_req; +uint32_t mem_sel; + +void mem_ram_select(int select) +{ + ram_sel = select; + switch (ram_sel) + { + case 0: + nrf_gpio_pin_clear(RAM_SEL_PIN); + break; + case 1: + nrf_gpio_pin_set(RAM_SEL_PIN); + break; + default: + break; + } + NRF_LOG_INFO("Select SRAM: %d", ram_sel); +} + +void mem_ram_toggle(void) +{ + mem_ram_select(ram_sel ^ 1); +} + +extern int sram_drv_write(uint32_t addr, void *p_dest, uint32_t len); +extern int sram_drv_read(uint32_t addr, void *p_dest, uint32_t len); + +static bool chk_sram_swtich_evt(uint32_t *new_ram_sel) +{ + /************************************************ + * When the mem_sel is in a low-level state, + * the state of mem_req is considered valid. + ************************************************/ + while (mem_sel == false) + { + vTaskDelay(pdMS_TO_TICKS(5)); + if (mem_req != ram_sel) + { + *new_ram_sel = mem_req; + return true; + } + } + + return false; +} +static void mem_drv_task(void *p_arg) +{ + extern void sram_drv_init(void); + sram_drv_init(); + + extern void sram_drv_reset(void); + for (int i = 0; i < 2; i++) + { + mem_ram_toggle(); + sram_drv_reset(); + } + + for (;;) + { + uint32_t new_ram_sel; + + xSemaphoreTake(mem_sel_semphr, portMAX_DELAY); + + if (chk_sram_swtich_evt(&new_ram_sel) == false) + { + NRF_LOG_INFO("no switch sram"); + continue; + } + + NRF_LOG_INFO("found ram sel != mem req, delay 100ms"); + vTaskDelay(pdMS_TO_TICKS(100)); + + uint32_t green_frame_size = sizeof(mem_data.green_frame); + uint32_t red_frame_size = 0; + uint32_t total_size = 0; + if (mem_available_cnt > 3) + { + /* read red frame data from streambuffer */ + taskENTER_CRITICAL(); + mem_available_cnt = 0; + red_frame_size = xStreamBufferReceive(mem_drv_stream, mem_data.red_frame, sizeof(mem_data.red_frame), 0); + taskEXIT_CRITICAL(); + } + + /* write green & red frame data to sram */ + total_size = green_frame_size + red_frame_size; + mem_data.green_frame.header[0].len = __REVSH(total_size); + mem_data.green_frame.header[0].marker = __REVSH(0xA55A); + mem_data.green_frame.header[1].val = mem_data.green_frame.header[0].val; + mem_data.green_frame.header[2].val = mem_data.green_frame.header[0].val; + sram_drv_write(0x0000, &mem_data, total_size); + + /* switch sram */ + mem_ram_select(new_ram_sel); + +#if MEM_DUMP + for (uint32_t i = 0; i < total_size / 32; i++) + { + uint8_t *p = (uint8_t *)&mem_data; + NRF_LOG_HEXDUMP_INFO(&p[i * 32], 32); + } + if (total_size % 32) + { + uint8_t *p = (uint8_t *)&mem_data; + NRF_LOG_HEXDUMP_INFO(&p[(total_size / 32) * 32], total_size % 32); + } +#endif + NRF_LOG_INFO("Write: %d bytes, and switch sram done!!!", total_size); + } +} + +void mem_board_reset(void) +{ + mem_available_cnt = 0; + mem_notify_cnt = 0; + xStreamBufferReset(mem_drv_stream); +} + +void mem_notify_cb(uint8_t *p, uint32_t len) +{ + /* write red frame data to streambuffer */ + taskENTER_CRITICAL(); + static struct + { + uint8_t prefix; + uint8_t cnt; + uint8_t len; + uint8_t content[64]; + } swap_buf; + + swap_buf.prefix = 0xFF; + swap_buf.cnt = mem_notify_cnt++; + swap_buf.len = len; + memcpy(swap_buf.content, p, len); + + swap_buf.content[len + 0] = 0; + swap_buf.content[len + 1] = 0; + swap_buf.content[len + 2] = 0; + swap_buf.content[len + 3] = 0; + swap_buf.content[len + 4] = 0; + + uint32_t sum = 0; + for (int i = 0; i < len; i++) + { + sum += p[i]; + } + sum += swap_buf.prefix; + sum += swap_buf.cnt; + sum += swap_buf.len; + swap_buf.content[len + 5] = sum & 0xFF; + xStreamBufferSend(mem_drv_stream, &swap_buf, 3 + len + 6, 0); + mem_available_cnt++; + taskEXIT_CRITICAL(); +} + +void mem_board_init(void) +{ + // Config RAM test pin + nrf_gpio_cfg_input(MEM_TEST_01_PIN, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(MEM_TEST_02_PIN, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(MEM_TEST_03_PIN, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(MEM_TEST_04_PIN, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(MEM_TEST_05_PIN, NRF_GPIO_PIN_PULLUP); + + // Config RAM select pin + nrf_gpio_cfg_output(RAM_SEL_PIN); + nrf_gpio_pin_clear(RAM_SEL_PIN); + + // Config PI Ctrl pin + nrf_gpio_cfg_input(MEM_SEL_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(MEM_REQ_PIN, NRF_GPIO_PIN_NOPULL); + + nrf_gpiote_event_configure(MEM_SEL_GPIOTE_ID, MEM_SEL_PIN, NRF_GPIOTE_POLARITY_TOGGLE); + nrf_gpiote_event_enable(MEM_SEL_GPIOTE_ID); + nrf_gpiote_int_enable(0x01 << MEM_SEL_GPIOTE_ID); + + nrf_gpiote_event_configure(MEM_REQ_GPIOTE_ID, MEM_REQ_PIN, NRF_GPIOTE_POLARITY_TOGGLE); + nrf_gpiote_event_enable(MEM_REQ_GPIOTE_ID); + nrf_gpiote_int_enable(0x01 << MEM_REQ_GPIOTE_ID); + + // Create Semphr & Task + mem_sel_semphr = xSemaphoreCreateBinary(); + mem_drv_stream = xStreamBufferCreate(MEM_DATA_UNIT * 32, 1); + 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_sel_isr(void) +{ + mem_sel = nrf_gpio_pin_read(MEM_SEL_PIN); + if (mem_sel == 0) + { + BaseType_t xHigherPriorityTaskWoken; + xSemaphoreGiveFromISR(mem_sel_semphr, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} + +static void mem_req_isr(void) +{ + mem_req = nrf_gpio_pin_read(MEM_REQ_PIN); +} + +void GPIOTE_IRQHandler(void) +{ + if (NRF_GPIOTE->EVENTS_IN[MEM_SEL_GPIOTE_ID]) + { + NRF_GPIOTE->EVENTS_IN[MEM_SEL_GPIOTE_ID] = 0; + mem_sel_isr(); + return; + } + if (NRF_GPIOTE->EVENTS_IN[MEM_REQ_GPIOTE_ID]) + { + NRF_GPIOTE->EVENTS_IN[MEM_REQ_GPIOTE_ID] = 0; + mem_req_isr(); + return; + } +} diff --git a/nrf5x.props b/nrf5x.props index c0a601e..81a25dd 100644 --- a/nrf5x.props +++ b/nrf5x.props @@ -18,7 +18,7 @@ $(BSP_ROOT)/nRF5x/LinkerScripts/nRF52840_XXAA_S140_reserve.lds $(BSP_ROOT)/nRF5x/SoftdeviceLibraries/hard;$(BSP_ROOT)/nRF5x/LinkerScripts;%(Link.LibrarySearchDirectories) - --specs=nano.specs -u _printf_float --specs=nosys.specs -mabi=aapcs %(Link.AdditionalOptions) + --specs=nano.specs -u _printf_float --specs=nosys.specs -Wl,--no-warn-rwx-segments -mabi=aapcs %(Link.AdditionalOptions) diff --git a/nrf5x.xml b/nrf5x.xml index 0f8259b..b56714d 100644 --- a/nrf5x.xml +++ b/nrf5x.xml @@ -2,9 +2,9 @@ com.visualgdb.arm-eabi - 10.3.1 - 10.2.90 - 1 + 12.2.1 + 12.2 + 2 com.sysprogs.arm.nordic.nrf5x 17.0 diff --git a/scripts/host_cmd.py b/scripts/host_cmd.py index 25c919c..4370974 100644 --- a/scripts/host_cmd.py +++ b/scripts/host_cmd.py @@ -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) diff --git a/sram_drv.c b/sram_drv.c index d1f5dfc..de21fa2 100644 --- a/sram_drv.c +++ b/sram_drv.c @@ -29,10 +29,12 @@ extern "C" #define READ_STATUS_CMD (0b00000101) #define WRITE_STATUS_CMD (0b00000001) -#define BYTE_MODE (0b00) -#define PAGE_MODE (0b10) -#define SEQ_MODE (0b01) -#define RESVD_MODE (0b11) +#define BYTE_MODE (0b00000010) +#define PAGE_MODE (0b10000010) +#define SEQ_MODE (0b01000010) +#define RESVD_MODE (0b11000010) + +#define HOLD_DISABLE (0b00000001) #if (SRAM_DEVICE == SRAM_23K640) #define SRAM_SIZE (64 * 1024 / 8) @@ -43,20 +45,14 @@ extern "C" #endif #define SRAM_SPIM (NRF_SPIM3) -#define CS0_PIN NRF_GPIO_PIN_MAP(1, 11) -#define CS1_PIN NRF_GPIO_PIN_MAP(1, 12) -#define SCLK_PIN NRF_GPIO_PIN_MAP(1, 13) -#define MOSI_PIN NRF_GPIO_PIN_MAP(1, 14) -#define MISO_PIN NRF_GPIO_PIN_MAP(1, 15) +#define CS_PIN NRF_GPIO_PIN_MAP(0, 7) +#define SCLK_PIN NRF_GPIO_PIN_MAP(0, 12) +#define MOSI_PIN NRF_GPIO_PIN_MAP(0, 14) +#define MISO_PIN NRF_GPIO_PIN_MAP(0, 11) static SemaphoreHandle_t txrx_end_sem; static SemaphoreHandle_t sram_mutex; -const uint8_t cs_bank[SRAM_BANK_NUM] = { - CS0_PIN, - CS1_PIN -}; - static void write_bytes(void *p, uint32_t len) { nrf_spim_tx_buffer_set(SRAM_SPIM, p, len); @@ -73,6 +69,16 @@ static void read_bytes(void *p, uint32_t len) xSemaphoreTake(txrx_end_sem, portMAX_DELAY); } +static void read_write_bytes(void *tx, uint32_t tx_len, void *rx, uint32_t rx_len) +{ + static uint8_t recv[256]; + nrf_spim_tx_buffer_set(SRAM_SPIM, tx, tx_len); + nrf_spim_rx_buffer_set(SRAM_SPIM, recv, tx_len + rx_len); + nrf_spim_task_trigger(SRAM_SPIM, NRF_SPIM_TASK_START); + xSemaphoreTake(txrx_end_sem, portMAX_DELAY); + memcpy(rx, &recv[tx_len], rx_len); +} + static void write_status(uint8_t mode) { uint8_t buf[] = { @@ -80,6 +86,14 @@ static void write_status(uint8_t mode) }; write_bytes(buf, sizeof(buf)); } + +static void read_status(uint8_t *mode) +{ + uint8_t send[] = { + READ_STATUS_CMD + }; + read_write_bytes(send, sizeof(send), mode, sizeof(*mode)); +} static void write_inst_addr(uint32_t inst, uint32_t addr) { uint8_t buf[] = { @@ -90,37 +104,57 @@ static void write_inst_addr(uint32_t inst, uint32_t addr) write_bytes(buf, sizeof(buf)); } -void sram_drv_write_status(uint32_t bank, uint8_t mode) +void sram_drv_write_status(uint8_t mode) { xSemaphoreTake(sram_mutex, portMAX_DELAY); - nrf_gpio_pin_clear(cs_bank[bank & 0x01]); - write_status(mode); - nrf_gpio_pin_set(cs_bank[bank & 0x01]); + nrf_gpio_pin_clear(CS_PIN); + write_status(mode | HOLD_DISABLE); + nrf_gpio_pin_set(CS_PIN); xSemaphoreGive(sram_mutex); } -int sram_drv_write(uint32_t bank, uint32_t addr, void *p_dest, uint32_t len) +void sram_drv_read_status(uint8_t *mode) { xSemaphoreTake(sram_mutex, portMAX_DELAY); - nrf_gpio_pin_clear(cs_bank[bank & 0x01]); + nrf_gpio_pin_clear(CS_PIN); + read_status(mode); + nrf_gpio_pin_set(CS_PIN); + xSemaphoreGive(sram_mutex); +} +int sram_drv_write(uint32_t addr, void *p_dest, uint32_t len) +{ + xSemaphoreTake(sram_mutex, portMAX_DELAY); + nrf_gpio_pin_clear(CS_PIN); write_inst_addr(WRITE_CMD, addr); write_bytes(p_dest, len); - nrf_gpio_pin_set(cs_bank[bank & 0x01]); + nrf_gpio_pin_set(CS_PIN); xSemaphoreGive(sram_mutex); return 0; } -int sram_drv_read(uint32_t bank, uint32_t addr, void *p_dest, uint32_t len) +int sram_drv_read(uint32_t addr, void *p_dest, uint32_t len) { xSemaphoreTake(sram_mutex, portMAX_DELAY); - nrf_gpio_pin_clear(cs_bank[bank & 0x01]); + nrf_gpio_pin_clear(CS_PIN); write_inst_addr(READ_CMD, addr); read_bytes(p_dest, len); - nrf_gpio_pin_set(cs_bank[bank & 0x01]); + nrf_gpio_pin_set(CS_PIN); xSemaphoreGive(sram_mutex); return 0; } +static uint8_t dummy[32] = { 0 }; +void sram_drv_reset(void) +{ + sram_drv_write_status(SEQ_MODE); + memset(dummy, 0x00, COUNTOF(dummy)); + for (int i = 0; i < SRAM_SIZE / COUNTOF(dummy); i++) + { + uint32_t addr = i * COUNTOF(dummy); + sram_drv_write(addr, dummy, sizeof(dummy)); + } +} + void sram_drv_init(void) { txrx_end_sem = xSemaphoreCreateBinary(); @@ -133,12 +167,9 @@ void sram_drv_init(void) // Config SPI clk pin nrf_gpio_cfg_output(SCLK_PIN); nrf_gpio_pin_clear(SCLK_PIN); - // Config SPI cs0 pin - nrf_gpio_cfg_output(CS0_PIN); - nrf_gpio_pin_set(CS0_PIN); - // Config SPI cs1 pin - nrf_gpio_cfg_output(CS1_PIN); - nrf_gpio_pin_set(CS1_PIN); + // Config SPI cs pin + nrf_gpio_cfg_output(CS_PIN); + nrf_gpio_pin_set(CS_PIN); // Config SPI module nrf_spim_configure(SRAM_SPIM, NRF_SPIM_MODE_0, NRF_SPIM_BIT_ORDER_MSB_FIRST); @@ -153,9 +184,6 @@ void sram_drv_init(void) sd_nvic_SetPriority(SPIM3_IRQn, _PRIO_APP_MID); sd_nvic_EnableIRQ(SPIM3_IRQn); nrf_spim_int_enable(SRAM_SPIM, NRF_SPIM_INT_END_MASK); - - sram_drv_write_status(0, SEQ_MODE); - sram_drv_write_status(1, SEQ_MODE); } void SPIM3_IRQHandler(void) diff --git a/syscalls.c b/syscalls.c new file mode 100644 index 0000000..fadb992 --- /dev/null +++ b/syscalls.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + + +/* 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; +} diff --git a/uart_drv.c b/uart_drv.c index ce30ae3..75a2fa9 100644 --- a/uart_drv.c +++ b/uart_drv.c @@ -21,8 +21,8 @@ extern "C" #endif #define HOST_UART (NRF_UARTE0) -#define HOST_UART_DRV_TX_PIN 6 -#define HOST_UART_DRV_RX_PIN 8 +#define HOST_UART_DRV_TX_PIN NRF_GPIO_PIN_MAP(0, 4) +#define HOST_UART_DRV_RX_PIN NRF_GPIO_PIN_MAP(0, 27) static SemaphoreHandle_t uart_drv_tx_sem; static SemaphoreHandle_t uart_drv_rx_sem; @@ -76,7 +76,7 @@ void uart_drv_init(void) nrf_gpio_cfg_output(HOST_UART_DRV_TX_PIN); nrf_gpio_cfg_input(HOST_UART_DRV_RX_PIN, NRF_GPIO_PIN_NOPULL); nrf_uarte_configure(HOST_UART, NRF_UARTE_PARITY_EXCLUDED, NRF_UARTE_HWFC_DISABLED); - nrf_uarte_baudrate_set(HOST_UART, NRF_UARTE_BAUDRATE_57600); + nrf_uarte_baudrate_set(HOST_UART, NRF_UARTE_BAUDRATE_115200); nrf_uarte_txrx_pins_set(HOST_UART, HOST_UART_DRV_TX_PIN, HOST_UART_DRV_RX_PIN); nrf_uarte_hwfc_pins_disconnect(HOST_UART); nrf_uarte_enable(HOST_UART);