Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite busy #69

Closed
fabiencomte opened this issue Aug 26, 2015 · 11 comments
Closed

Infinite busy #69

fabiencomte opened this issue Aug 26, 2015 · 11 comments

Comments

@fabiencomte
Copy link

Hello,

I tried this code on 3 boards to make a triangle to test central and device role at same time with S130 on nRF51.

frequently, i loop in busy (2) and never goes out. Maybe i did a mistake, this is my code.

include "mbed.h"

include "BLE.h"

include "UARTService.h"

include "ble/DiscoveredCharacteristic.h"

include "ble/DiscoveredService.h"

include "UARTService.h"

define SOFT_DEVICE_FATHER_HANDLE 3

define BOARDS_COUNT 3

const Gap::Address_t mac_board_0 = {0xb8, 0xac, 0x4e, 0x8d, 0x8b, 0xeb};
const Gap::Address_t mac_board_1 = {0x9c, 0x43, 0x62, 0x30, 0xaf, 0xd2};
const Gap::Address_t mac_board_2 = {0x5f, 0x1a, 0x9e, 0x6a, 0x63, 0xdd};

// tiny ble board

define LED_GREEN p21

define LED_RED p22

define LED_BLUE p23

define BUTTON_PIN p17

define BATTERY_PIN p1

define MPU6050_SDA p12

define MPU6050_SCL p13

define UART_TX p9

define UART_RX p11

define UART_CTS p8

define UART_RTS p10

DigitalOut led(LED_RED);
DigitalOut alivenessLED(LED_GREEN);
InterruptIn button(BUTTON_PIN);
AnalogIn battery(BATTERY_PIN);
Serial pc(UART_TX, UART_RX);

bool mac_equals(const Gap::Address_t mac_1, const Gap::Address_t mac_2)
{
#if 0
if (mac_1[0] != mac_2[0])
{
return false;
}
if (mac_1[1] != mac_2[1])
{
return false;
}
if (mac_1[2] != mac_2[2])
{
return false;
}
if (mac_1[3] != mac_2[3])
{
return false;
}
if (mac_1[4] != mac_2[4])
{
return false;
}
if (mac_1[5] != mac_2[5])
{
return false;
}
#else
for (int i = 0; i < 6; i++)
{
if (mac_1[i] != mac_2[i])
{
//pc.printf("0x%02x != 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
return false;
}
else
{
//pc.printf("0x%02x == 0x%02x at %d\r\n", mac_1[i], mac_2[i], i);
}
}
#endif
return true;
}

int get_board_index(const Gap::Address_t mac)
{
if (mac_equals(mac, mac_board_0))
{
return 0;
}
if (mac_equals(mac, mac_board_1))
{
return 1;
}
if (mac_equals(mac, mac_board_2))
{
return 2;
}

return -1;

}

void periodicCallback(void)
{
alivenessLED = !alivenessLED; /* do blinky on alivenessLED while we're waiting for BLE events */
}

// Mixed role ****************************************************
BLE ble;
Gap::Address_t my_mac;
int my_board_index = -1;

// Device role ****************************************************
UARTService * uartServicePtr = NULL;
const static char DEVICE_NAME[] = "ChangeMe!!"; // change this
static const uint16_t uuid16_list[] = {UARTServiceShortUUID};

// Central role ****************************************************
Gap::Handle_t connectionHandle = 0xFFFF;
DiscoveredCharacteristic uartTXCharacteristic;
DiscoveredCharacteristic uartRXCharacteristic;
bool foundUartRXCharacteristic = false;

// Device role ****************************************************
void onReceivedDataFromCentralCallback(const GattWriteCallbackParams *params)
{
if (uartServicePtr != NULL)
{
if ((params->handle == uartServicePtr->getTXCharacteristicHandle()) && (params->len >= 1))
{
if (params->data[0] != '0')
{
led = 1;
}
else
{
led = 0;
}

        for(int i = 0; i < params->len; i++) 
        {
            pc.printf("%c", params->data[i]);
        }

        pc.printf(" (%d, %d)\r\n", params->handle, params->connHandle);
    }
}

}

// Central role ****************************************************
void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params)
{
// do connections like a triangle
int peer_board_index = get_board_index(params->peerAddr);

int next_board_index = my_board_index + 1;
if (next_board_index >= BOARDS_COUNT)
{
    next_board_index = 0;
}

//pc.printf("adv %d, %d, %d\r\n", peer_board_index, my_board_index, next_board_index);

if (peer_board_index == next_board_index)
{
    pc.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n",
           params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],
           params->rssi, params->isScanResponse, params->type);

    ble.gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
}

}

void serviceDiscoveryCallback(const DiscoveredService *service)
{
if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT)
{
pc.printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
}
else
{
pc.printf("S UUID-");
const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++)
{
pc.printf("%02x", longUUIDBytes[i]);
}
pc.printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
}
}

void characteristicDiscoveryCallback(const DiscoveredCharacteristic characteristicP)
{
pc.printf(" C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
if (characteristicP->getUUID().getShortUUID() == UARTServiceTXCharacteristicShortUUID)
{
pc.printf("fit TX 0x%04x\r\n", UARTServiceTXCharacteristicShortUUID);
/
!ALERT! Alter this filter to suit your device. /
uartTXCharacteristic = *characteristicP;
}
else if (characteristicP->getUUID().getShortUUID() == UARTServiceRXCharacteristicShortUUID)
{
pc.printf("fit RX 0x%04x\r\n", UARTServiceRXCharacteristicShortUUID);
/
!ALERT! Alter this filter to suit your device. */
uartRXCharacteristic = *characteristicP;
foundUartRXCharacteristic = true;
}
}

void discoveryTerminationCallback(Gap::Handle_t connectionHandle)
{
pc.printf("terminated SD for handle %u\r\n", connectionHandle);
}

void onReceivedDataFromDeviceCallback(const GattHVXCallbackParams *params)
{
//pc.printf("received HVX callback for handle %u; type %s\r\r\n", params->handle, (params->type == BLE_HVX_NOTIFICATION) ? "notification" : "indication");
if (params->type == BLE_HVX_NOTIFICATION)
{
if ((params->handle == uartRXCharacteristic.getValueHandle()) && (params->len > 0))
{
for (int i = 0; i < params->len; i++)
{
pc.printf("%c", params->data[i]);
}

        pc.printf(" (%d, %d, %d)\r\n", params->handle, params->connHandle, uartRXCharacteristic.getValueHandle());
    }
}
//pc.printf("\r\n");

}

// Mixed role ****************************************************
void connectionCallback(const Gap::ConnectionCallbackParams_t params)
{
if (params->role == Gap::CENTRAL)
{
pc.printf("connected as central (handle = %d)\r\n\r", params->handle);
connectionHandle = params->handle;
ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback/
, 0xa000, 0xa001*/);
}
else
{
pc.printf("connected as device (handle = %d)\r\n\r", params->handle);

    pc.printf("Conn. params => min=%d, max=%d, slave=%d, supervision=%d\r\n", params->connectionParams->minConnectionInterval, params->connectionParams->maxConnectionInterval, params->connectionParams->slaveLatency, params->connectionParams->connectionSupervisionTimeout);

    Gap::ConnectionParams_t connectionParams;
    connectionParams.minConnectionInterval        = 6;
    connectionParams.maxConnectionInterval        = 12;
    connectionParams.slaveLatency                 = 0;
    connectionParams.connectionSupervisionTimeout = 500;

    if (ble.updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) 
    {
        pc.printf("failed to update connection parameter\r\n");
    }
}
pc.printf("own %02x:%02x:%02x:%02x:%02x:%02x (%s), peer %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", params->ownAddr[5], params->ownAddr[4], params->ownAddr[3], params->ownAddr[2], params->ownAddr[1], params->ownAddr[0], (params->ownAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random", params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0], (params->peerAddrType == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random");

}

void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
pc.printf("disconnected (handle = %d)\r\n", handle);

if (handle == SOFT_DEVICE_FATHER_HANDLE)
{
    // restart advertising
    ble.startAdvertising(); 
}
else
{
    // restart scan
    ble.gap().startScan(advertisementCallback);
}

}

void serialTxCallback()
{

}

int rx_char = -1;
void serialRxCallback()
{
if (rx_char != -1)
{
pc.printf("overflow\r\n");
}

 //computer.putc(computer.getc());
 rx_char = pc.getc();

}

int main(void)
{
alivenessLED = 0;

pc.baud(115200);
//pc.attach(&serialTxCallback, Serial::TxIrq);
pc.attach(&serialRxCallback, Serial::RxIrq);

// clear terminal output
for (int k = 0; k < 255; k++)
{
    pc.printf("\r\n");    
}

pc.printf("Central and device\r\n");

Ticker ticker;
ticker.attach(periodicCallback, 1);


// Mixed role ****************************************************
ble.init();

Gap::AddressType_t my_mac_type;
ble.gap().getAddress(&my_mac_type, my_mac);
my_board_index = get_board_index(my_mac);
pc.printf("me %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0], (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random");


// try to speed up but looks like if it was ignored
Gap::ConnectionParams_t fast;
if (ble.getPreferredConnectionParams(&fast) != BLE_ERROR_NONE) 
{
    pc.printf("getPreferredConnectionParams failed\r\n");
}
else
{
    fast.minConnectionInterval = 16; // 20 ms
    fast.maxConnectionInterval = 32; // 40 ms
    fast.slaveLatency = 0;
    if (ble.gap().setPreferredConnectionParams(&fast) != BLE_ERROR_NONE) 
    {
        pc.printf("setPreferredConnectionParams failed\r\n");
    }
}
ble.gap().onConnection(connectionCallback);
ble.gap().onDisconnection(disconnectionCallback);

// Device role ****************************************************
ble.gattServer().onDataWritten(onReceivedDataFromCentralCallback);

UARTService uartService(ble);
uartServicePtr = &uartService;

// setup advertising
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type
ble.setAdvertisingInterval(100); 

// Central role ****************************************************
ble.gattClient().onHVX(onReceivedDataFromDeviceCallback);
ble.gap().setScanParams(500, 450);


// start advertising and scan
ble.startAdvertising(); 
ble.gap().startScan(advertisementCallback);

while (true) 
{
      // allow notifications from device
      if (foundUartRXCharacteristic && !ble.gattClient().isServiceDiscoveryActive()) 
      {
        foundUartRXCharacteristic = false; /* need to do the following only once */

        uint16_t value = BLE_HVX_NOTIFICATION;
        ble.gattClient().write(GattClient::GATT_OP_WRITE_REQ,
                               connectionHandle,
                               uartRXCharacteristic.getValueHandle() + 1, /* HACK Alert. We're assuming that CCCD descriptor immediately follows the value attribute. */
                               sizeof(uint16_t),                          /* HACK Alert! size should be made into a BLE_API constant. */
                               reinterpret_cast<const uint8_t *>(&value));
    }

    // while a new char from computer is available
    while (rx_char != -1)
    {
        uint8_t command = rx_char;
        rx_char = -1;

        uint8_t temp[20];
        int length = 1;

        // if special char to test a 20 bytes frame
        if (command == '*')
        {
            pc.printf("20 chars\r\n");

            int c = 0;
            for (c = 0; c < 20; c++)
            {
                temp[c] = 'a' + c;
            }
            length = 20;
        }
        else
        {
            temp[0] = command;
        }

        // central to device 
        while (1)
        {                    
            int ret = uartTXCharacteristic.write(length, temp);
            if (ret == BLE_ERROR_NONE) 
            {
                break;
            }   
            else if (ret == BLE_STACK_BUSY) 
            {
                pc.printf("\r\nbusy (1)\r\n");
                //break;
            }
            else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED) 
            {
                pc.printf("\r\nnot connected (1)\r\n");
                break;
            }
            else
            {
                pc.printf("\r\ncode %d (1)\r\n", ret);
            }
        }

        // device to central
        while (1)
        {                        
            if (!ble.gap().getState().connected) 
            {
                break;
            }
            int ret = ble.gattServer().write(uartServicePtr->getRXCharacteristicHandle(), temp, length);
            if (ret == BLE_ERROR_NONE) 
            {
                break;
            }
            else if (ret == BLE_STACK_BUSY) 
            {
                pc.printf("\r\nbusy (2)\r\n");
                //break;
            }
            else if (ret == BLE_ERROR_OPERATION_NOT_PERMITTED) 
            {
                pc.printf("\r\nnot connected (2)\r\n");
                break;
            }
            else
            {
                pc.printf("\r\ncode %d (2)\r\n", ret);
            }
        }
    }

    ble.waitForEvent(); // save power
}

}

@ghost
Copy link

ghost commented Oct 16, 2015

@rainierwolfcastle : that url doesn't seem valid (or is broken). says server doesn't exist

@rgrover
Copy link
Contributor

rgrover commented Oct 16, 2015

@jrobeson that's an ARM internal URL

@ghost
Copy link

ghost commented Oct 16, 2015

then they should prefix those messages saying so :) I doubt I'll be the last to mention it.

@ghost
Copy link

ghost commented Oct 16, 2015

@fabiencomte: you should post this program as a gist, it'd be a lot easier to read that way. Also, cut it down to the minimal amount of code to reproduce the problem.

@rgrover
Copy link
Contributor

rgrover commented Oct 16, 2015

@jrobeson you're right. they should be marked as ARM internal

@0xc0170
Copy link

0xc0170 commented Oct 16, 2015

Definitely, I thought the plan was to add there internal word. sorry for confusion

@rainierwolfcastle
Copy link

ARM Internal Ref: IOTSFW-1032

@rgrover
Copy link
Contributor

rgrover commented Oct 20, 2015

@fabiencomte is this still an issue for you?

@ghost
Copy link

ghost commented Feb 11, 2016

I guess it can be closed then?

@fabiencomte
Copy link
Author

Hello,

Sorry, i missed previous messages notifications. I moved to Nordic SDK to avoid this issue.

@fabiencomte
Copy link
Author

Yes we can close

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants