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,
Does the merged code build without any errors?
regards
Jared
So please clarify, when you see log output, what log output you see, and from what device,
This is what I see on responder and on tester terminal if I try to integrate my code with SPI code.
And this is what I see if I run just the code ble_app_att_mtu_throughput:
Then, If I comment the SPI part of the code, it runs perfectly. But I need the SPI part.
So you only see the log output if you only connect the client side?
Not if I integrate the SPI code
The project you shared doesn't contain any source file?
Sorry, is it right now?
Hi,
Thank you for the clear explanation.
The zip file does still not contain any main.c or any other source file as far as I can see. You're using Segger Embedded Studio as IDE right?
regards
Jared
Yes, I'm using SEGGER
Can you send me zip that contains your project code? Meaning main.c and any other source file you've added.
2843.ble_app_att_mtu_throughput.zip
Sorry again
2843.ble_app_att_mtu_throughput.zip
Sorry again
I have so many doubt.
I don't know if you run the ble_app_att_mtu_throughput code, but normally you charge the code on the first nRF52832 and on the second nRF52832 and you can choose which one is the tester (the Central) and which one is the responder (the Peripheral). Once you choose it, data is sent from tester to responder.
Now, once I choose which one is the tester and which one is the responder, before send data via ble, start the spis code (in meanwhile I start the spi code in the nRF52840 which send data via spi) which is the part that allow to receive data, then send data via BLE.
Just to simplify the reading of the code. Before I tried to add the SPIS part, data were generated in the amts.c as mentioned in line 220-222:
for (uint16_t i = 0; i < payload_len; i++) { data[i] = i % 244; // Riempie il buffer con valori da 0 a 243 }
so I think I should work there.
sorry for late response here Stefano, Jared is away and will be back on Monday. Thanks for your patience so far.
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