Hi,
I'm struggling to use ble_app_att_mtu_throughput and spi. Some help?
When I merge the two codes the main code (ble_app_att_mtu_throughput) doesn't work.
Thanks for your help
Hi,
I'm struggling to use ble_app_att_mtu_throughput and spi. Some help?
When I merge the two codes the main code (ble_app_att_mtu_throughput) doesn't work.
Thanks for your help
Hi Susheel,
Thanks. Meanwhile, adding what I said to Jared in previous messages, I show you something else.
This is a simply spi-spis SPI comunication where I send via SPI 10 packets of 244 bytes (from 0 to 243) from the Master and these bytes arrives to the Slave. I'll show just the firsts 10 bytes for each packets to avoid filling the buffer log:
I verified bytes are succesfully send/received for each packets.
The problem come when I run on the the board which receive data via spi (so the board where I charge spis) the ble_att_app_mtu_thrpughput+spis:
This image show what I receive via spi with this code.
The news (compared to what I said to Jared) is that I'm trying to implement the spis part of the code on the amts.c and not in the main.c:
#include "amt.h" #include "app_error.h" #include "ble_err.h" #include "ble_srv_common.h" #include "nrf_error.h" #include "sdk_common.h" #include "nrf_drv_spis.h" #define NRF_LOG_MODULE_NAME AMTS #include "nrf_log.h" NRF_LOG_MODULE_REGISTER(); #define OPCODE_LENGTH 1 /**< Length of opcode inside a notification. */ #define HANDLE_LENGTH 2 /**< Length of handle inside a notification. */ static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(1); #define MAX_PACKET_SIZE 244 static uint8_t m_tx_buf[MAX_PACKET_SIZE] = {0}; static uint8_t m_rx_buf[MAX_PACKET_SIZE + 1]; static const uint8_t m_length = MAX_PACKET_SIZE; static volatile bool spis_xfer_done = false; static uint8_t packets_received = 0; static nrf_ble_amts_t *p_ctx; void spis_event_handler(nrf_drv_spis_event_t event) { if (event.evt_type == NRF_DRV_SPIS_XFER_DONE) { spis_xfer_done = true; packets_received++; NRF_LOG_INFO("SPIS Transfer completed. Received data:"); for (uint8_t i = 0; i < m_length; i++) { NRF_LOG_INFO("%03d", m_rx_buf[i]); // Log in decimal } if (p_ctx->conn_handle != BLE_CONN_HANDLE_INVALID) { // Aggiorna bytes_sent con la lunghezza dei dati ricevuti via SPI p_ctx->bytes_sent += m_length; // Invia i dati ricevuti via SPI tramite BLE nrf_ble_amts_send(p_ctx, m_rx_buf, m_length); // Genera l'evento per la trasmissione dei dati nrf_ble_amts_evt_t evt; evt.evt_type = NRF_BLE_AMTS_EVT_TRANSFER_244B; evt.bytes_transfered_cnt = p_ctx->bytes_sent; p_ctx->evt_handler(evt); } } } void spis_init(nrf_ble_amts_t *p_ctx) { nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG; spis_config.csn_pin = APP_SPIS_CS_PIN; spis_config.miso_pin = APP_SPIS_MISO_PIN; spis_config.mosi_pin = APP_SPIS_MOSI_PIN; spis_config.sck_pin = APP_SPIS_SCK_PIN; APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler)); } static void char_notification_send(nrf_ble_amts_t *p_ctx); /**@brief Function for handling the Connect event. * * @param p_ctx Pointer to the AMTS structure. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_connect(nrf_ble_amts_t *p_ctx, ble_evt_t const *p_ble_evt) { p_ctx->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; } /**@brief Function for handling the Disconnect event. * * @param p_ctx Pointer to the AMTS structure. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_disconnect(nrf_ble_amts_t *p_ctx, ble_evt_t const *p_ble_evt) { p_ctx->conn_handle = BLE_CONN_HANDLE_INVALID; } /**@brief Function for handling the TX_COMPLETE event. * * @param p_ctx Pointer to the AMTS structure. */ static void on_tx_complete(nrf_ble_amts_t *p_ctx) { if (p_ctx->busy) { p_ctx->busy = false; char_notification_send(p_ctx); } } /**@brief Function for handling the Write event. * * @param p_ctx Pointer to the AMTS structure. * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_write(nrf_ble_amts_t *p_ctx, ble_evt_t const *p_ble_evt) { ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; if ((p_evt_write->handle == p_ctx->amts_char_handles.cccd_handle) && (p_evt_write->len == 2)) { // CCCD written, call the application event handler. nrf_ble_amts_evt_t evt; if (ble_srv_is_notification_enabled(p_evt_write->data)) { evt.evt_type = NRF_BLE_AMTS_EVT_NOTIF_ENABLED; } else { evt.evt_type = NRF_BLE_AMTS_EVT_NOTIF_DISABLED; } p_ctx->evt_handler(evt); } } void nrf_ble_amts_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) { nrf_ble_amts_t *p_ctx = (nrf_ble_amts_t *)p_context; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: on_connect(p_ctx, p_ble_evt); break; case BLE_GAP_EVT_DISCONNECTED: on_disconnect(p_ctx, p_ble_evt); break; case BLE_GATTS_EVT_WRITE: on_write(p_ctx, p_ble_evt); break; case BLE_GATTS_EVT_HVN_TX_COMPLETE: on_tx_complete(p_ctx); break; default: break; } } void nrf_ble_amts_init(nrf_ble_amts_t *p_ctx, amts_evt_handler_t evt_handler) { ret_code_t err_code; uint16_t service_handle; ble_uuid_t ble_uuid; ble_uuid128_t base_uuid = {SERVICE_UUID_BASE}; err_code = sd_ble_uuid_vs_add(&base_uuid, &(p_ctx->uuid_type)); APP_ERROR_CHECK(err_code); ble_uuid.type = p_ctx->uuid_type; ble_uuid.uuid = AMT_SERVICE_UUID; // Add service. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &service_handle); APP_ERROR_CHECK(err_code); // Add AMTS characteristic. ble_add_char_params_t amt_params; memset(&amt_params, 0, sizeof(amt_params)); amt_params.uuid = AMTS_CHAR_UUID; amt_params.uuid_type = p_ctx->uuid_type; amt_params.max_len = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; amt_params.char_props.notify = 1; amt_params.cccd_write_access = SEC_OPEN; amt_params.is_var_len = 1; err_code = characteristic_add(service_handle, &amt_params, &(p_ctx->amts_char_handles)); APP_ERROR_CHECK(err_code); // Add AMT Received Bytes Count characteristic. ble_add_char_params_t amt_rbc_params; memset(&amt_rbc_params, 0, sizeof(amt_rbc_params)); amt_rbc_params.uuid = AMT_RCV_BYTES_CNT_CHAR_UUID; amt_rbc_params.uuid_type = p_ctx->uuid_type; amt_rbc_params.max_len = AMT_RCV_BYTES_CNT_MAX_LEN; amt_rbc_params.char_props.read = 1; amt_rbc_params.read_access = SEC_OPEN; err_code = characteristic_add(service_handle, &amt_rbc_params, &(p_ctx->amt_rbc_char_handles)); APP_ERROR_CHECK(err_code); p_ctx->evt_handler = evt_handler; spis_init(p_ctx); } void nrf_ble_amts_notif_spam(nrf_ble_amts_t *p_ctx) { p_ctx->kbytes_sent = 0; p_ctx->bytes_sent = 0; char_notification_send(p_ctx); } void nrf_ble_amts_on_gatt_evt(nrf_ble_amts_t *p_ctx, nrf_ble_gatt_evt_t const *p_gatt_evt) { if (p_gatt_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED) { p_ctx->max_payload_len = p_gatt_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; } } static void char_notification_send(nrf_ble_amts_t *p_ctx) { uint16_t payload_len = p_ctx->max_payload_len; nrf_ble_amts_evt_t evt; if (p_ctx->bytes_sent >= AMT_BYTE_TRANSFER_CNT) { evt.bytes_transfered_cnt = p_ctx->bytes_sent; evt.evt_type = NRF_BLE_AMTS_EVT_TRANSFER_FINISHED; p_ctx->evt_handler(evt); p_ctx->busy = false; p_ctx->bytes_sent = 0; p_ctx->kbytes_sent = 0; return; } ble_gatts_hvx_params_t hvx_param = { .type = BLE_GATT_HVX_NOTIFICATION, .handle = p_ctx->amts_char_handles.value_handle, .p_data = m_rx_buf, .p_len = &payload_len, }; uint32_t err_code = NRF_SUCCESS; uint16_t packets_to_send = PACKETS; while (err_code == NRF_SUCCESS && packets_to_send > 0) { err_code = sd_ble_gatts_hvx(p_ctx->conn_handle, &hvx_param); if (err_code == NRF_ERROR_RESOURCES) { // Wait for BLE_GATTS_EVT_HVN_TX_COMPLETE. p_ctx->busy = true; break; } else if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("sd_ble_gatts_hvx() failed: 0x%x", err_code); } p_ctx->bytes_sent += payload_len; if (p_ctx->kbytes_sent != (p_ctx->bytes_sent / 244)) { p_ctx->kbytes_sent = (p_ctx->bytes_sent / 244); NRF_LOG_INFO("Sending data: "); for (uint16_t i = 0; i < 10; i++) { NRF_LOG_INFO("Byte %d: %d", i, m_rx_buf[i]); } evt.evt_type = NRF_BLE_AMTS_EVT_TRANSFER_244B; evt.bytes_transfered_cnt = p_ctx->bytes_sent; p_ctx->evt_handler(evt); } packets_to_send--; } } void nrf_ble_amts_rbc_set(nrf_ble_amts_t *p_ctx, uint32_t byte_cnt) { uint8_t data[AMT_RCV_BYTES_CNT_MAX_LEN]; uint16_t len; ble_gatts_value_t value_param; memset(&value_param, 0x00, sizeof(value_param)); len = (uint16_t)uint32_encode(byte_cnt, data); value_param.len = len; value_param.p_value = data; ret_code_t err_code = sd_ble_gatts_value_set(p_ctx->conn_handle, p_ctx->amt_rbc_char_handles.value_handle, &value_param); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("sd_ble_gatts_value_set() failed: 0x%x", err_code); } } void nrf_ble_amts_send(nrf_ble_amts_t *p_ctx, uint8_t *data, uint16_t length) { if (p_ctx->conn_handle == BLE_CONN_HANDLE_INVALID) { NRF_LOG_ERROR("No connection established, cannot send data."); return; } ble_gatts_hvx_params_t hvx_params = { .type = BLE_GATT_HVX_NOTIFICATION, .handle = p_ctx->amts_char_handles.value_handle, .p_data = data, .p_len = &length, }; uint32_t err_code = sd_ble_gatts_hvx(p_ctx->conn_handle, &hvx_params); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("sd_ble_gatts_hvx() failed: 0x%x", err_code); } else { NRF_LOG_INFO("Data sent successfully."); } }
Thanks for all,
Best regards.
Hi,
Based on your latest answer, it seems like you are able to get logs compared to earlier. That is good.
I know understand that you are not getting the desired data on the log output from the SPI communication.
First step in debugging this is to either connect a logic analyzer or a oscilloscope to the MOSI/MISO pins, and confirm if the Master/slave is sending the expected data.
regards
Jared
Hi,
Is an SPI Driver suitable to this scope? For istance I connected the SPI Driver to the pins of the SPI Slave/Master but I see nothing (maybe because 0 is the data received
Yes, the SPI driver should be able to work along side the BLE samples. Did you probe the SPI lines as I suggested in my last reply?
Yes, I connected the MISO/MOSI to the SPI Driver but nothing happen. I think because 0 is transmitting.