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

GitHub Periodic Advertising example hangs when calling setPeriodicAdvertisingParameters (5.13.1 and master branch) #11106

Closed
lichangche opened this issue Jul 25, 2019 · 12 comments

Comments

@lichangche
Copy link

lichangche commented Jul 25, 2019

Description

Managed to get the periodic advertising example to run on NRF52840_DK but it hangs when calling setPeriodicAdvertisingParameters. 

I've tried on both release 5.13.1 and master branch, neither of them can pass the point when setPeriodicAdvertisingParameters is called.

I've also tried to debug and traced source code and seems only thing that matters are the WsfTaskLock call listed below. Any one bumped into similar issue? Any idea is this a bug of Mbed OS or a bug of the Periodical advertising example which I believe has been tested at some point? Anyone knows the version of the Mbed OS the exampled was tested with?

template
ble_error_t Gap::set_periodic_advertising_parameters_(
advertising_handle_t advertising_handle,
periodic_advertising_interval_t periodic_advertising_min,
periodic_advertising_interval_t periodic_advertising_max,
bool advertise_power
)
{
DmPerAdvIncTxPwr(advertising_handle, advertise_power);
DmPerAdvSetInterval(
advertising_handle,
periodic_advertising_min,
periodic_advertising_max
);
DmPerAdvConfig(advertising_handle);

return BLE_ERROR_NONE;

}

/************************************************************************************************/
/
!

  • \brief Set the minimum and maximum advertising intervals for periodic advertising.
  • \param advHandle Advertising handle.
  • \param intervalMin Minimum advertising interval.
  • \param intervalMax Maximum advertising interval.
  • \return None.
    /
    /
    ************************************************************************************************/
    void DmPerAdvSetInterval(uint8_t advHandle, uint16_t intervalMin, uint16_t intervalMax)
    {
    WSF_ASSERT(advHandle < DM_NUM_ADV_SETS);

WsfTaskLock();
dmPerAdvCb[advHandle].intervalMin = intervalMin;
dmPerAdvCb[advHandle].intervalMax = intervalMax;
WsfTaskUnlock();
}

/************************************************************************************************/
/
!

  • \brief Set whether or not to include TxPower in extended header of advertising PDU for
  •      periodic advertising.
    
  • \param advHandle Advertising handle.
  • \param incTxPwr Whether to include TxPower in extended header of advertising PDU (default
  •                   value is FALSE).
    
  • \return None.
    /
    /
    ************************************************************************************************/
    void DmPerAdvIncTxPwr(uint8_t advHandle, bool_t incTxPwr)
    {
    WSF_ASSERT(advHandle < DM_NUM_ADV_SETS);

WsfTaskLock();
dmPerAdvCb[advHandle].incTxPwr = incTxPwr;
WsfTaskUnlock();
}

Issue request type

[ ] Question
[ ] Enhancement
[X ] Bug
@lichangche
Copy link
Author

For anyone who is going to try the periodic advertising example, I had to modify the following line to get it run - otherwise there is an assertion failure due to configuration dependency:

Change from
adv_params.setType(ble::advertising_type_t::NON_CONNECTABLE_UNDIRECTED);
adv_params.setUseLegacyPDU(false);
to
adv_params.setType(ble::advertising_type_t::NON_CONNECTABLE_UNDIRECTED, false);

@ciarmcom
Copy link
Member

Internal Jira reference: https://jira.arm.com/browse/MBOCUSTRIA-1512

@lichangche
Copy link
Author

lichangche commented Jul 27, 2019

Some more information from my debug session via gdb:

Resetting target
(gdb) continue
Continuing.

Program received signal SIGTRAP, Trace/breakpoint trap.
0x01f41e24 in ?? ()
(gdb) backtrace
#0 0x01f41e24 in ?? ()
#1
#2 0x0006515a in __svcKernelStart () at mbed-os/rtos/TARGET_CORTEX/rtx5/RTX/Source/rtx_kernel.c:487
#3 osKernelStart () at mbed-os/rtos/TARGET_CORTEX/rtx5/RTX/Source/rtx_kernel.c:562
#4 0x00063f00 in mbed_rtos_start () at mbed-os/rtos/TARGET_CORTEX/mbed_rtos_rtx.c:116
#5 0x00063d72 in software_init_hook () at mbed-os/rtos/TARGET_CORTEX/TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c:52
#6 0x0000016e in _start ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

Here is the serial print out from the board - with my own added debug message:
DEVICE MAC ADDRESS: d0:7c:81:7a:c4:b5
start_role adver not ested
Scanning started
led blink
..
led blink
Scanning ended, failed to find peer
start_role scanner not ested
Set Adv params done
Advertising started for 5000ms
led blink
...
led blink
led blink
Connected to: d4:16:6e:75:2d:33
Roles established, my role is advter
Stopped advertising due to connection
led blink
...
led blink
Disconnected
start_role adver ested
schedule advertise_periodic
to start advertising for PA!
set periodic advertise params! <---- after this call, there is no more message, no led blink

Looks like something has triggered a reset/restart?

@lichangche
Copy link
Author

lichangche commented Jul 30, 2019

I've traced the issue using gdb and found it is stuck where a function pointer is used to call a function but the target function is never called and the same function pointer is called recursively until the stack got overflow and system crashes (see the above stack backtrace).

template
ble_error_t Gap::setPeriodicAdvertisingParameters(
advertising_handle_t handle,
periodic_interval_t periodicAdvertisingIntervalMin,
periodic_interval_t periodicAdvertisingIntervalMax,
bool advertiseTxPower
)
{
return impl()->setPeriodicAdvertisingParameters_(
handle,
periodicAdvertisingIntervalMin,
periodicAdvertisingIntervalMax,
advertiseTxPower
);
}

setPeriodicAdvertisingParameters should call setPeriodicAdvertisingParameters_ via function pointer;

actual result:

instead of calling the function, the function setPeriodicAdvertisingParameters is calling itself recursively;

Any ideas?

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 9, 2019

cc @ARMmbed/mbed-os-pan

@pan-
Copy link
Member

pan- commented Aug 9, 2019

@paul-szczepanek-arm I though this had been fixed . Could you confirm ?

@paul-szczepanek-arm
Copy link
Member

That has been fixed some time ago and continues to be fixed.

@lichangche
Copy link
Author

lichangche commented Aug 13, 2019

Not sure if anyone has really tried with the GitHub periodic advertising example but I don't agree that the bug can be closed.

As on 14th/Aug/2019, I tried it again using master branch and it remains the same hanging behaviour - and there is no update in 5.13 branch since it is released.

Actually I found in the following file, there may be a cyclic reference:
mbed-os/features/FEATURE_BLE/ble/pal/PalGap.h

ble_error_t set_periodic_advertising_parameters(
advertising_handle_t advertising_handle,
periodic_advertising_interval_t periodic_advertising_min,
periodic_advertising_interval_t periodic_advertising_max,
bool advertise_power
) {
return impl()->set_periodic_advertising_parameters(
advertising_handle,
periodic_advertising_min,
periodic_advertising_max,
advertise_power
);
}

By changing that to the following code, it does not hang any more - note the tiny underline '__' before the '(':
ble_error_t set_periodic_advertising_parameters(
advertising_handle_t advertising_handle,
periodic_advertising_interval_t periodic_advertising_min,
periodic_advertising_interval_t periodic_advertising_max,
bool advertise_power
) {
return impl()->set_periodic_advertising_parameters_(
advertising_handle,
periodic_advertising_min,
periodic_advertising_max,
advertise_power
);
}

Even it runs after this change, the periodic adverting example still breaks so far - in my test, the two nodes can establish their roles (after a number of changes including to change the first advertising type [not the periodic one] to legacy true, otherwise it spells out system error and crashes), the scanner will always return at this line:

    /* if we're looking for periodic advertising don't bother unless it's present */
    if (_role_established && !event.isPeriodicIntervalPresent()) {
        return;
    }

(From advertiser side, LE extended advs are happening but scanner can never detect the periodic interval !=0)

Can someone please run the example and verify this?

@paul-szczepanek-arm
Copy link
Member

paul-szczepanek-arm commented Aug 14, 2019

Apologies, you are right, there was the same exact error which has been fixed but different function. Was looking at setPeriodicAdvertisingParameters and not the pal version set_periodic_advertising_parameters. Will fix and rerun example.

@paul-szczepanek-arm
Copy link
Member

#11222

@lichangche
Copy link
Author

lichangche commented Aug 15, 2019

I could be wrong but likely the periodic interval field is always zero because when packets are constructed, it is always called isPeriodic false:

The same is true for all the instances where lctrPackAdvExtIndPdu are called.

pAdv->txAdvLen = lctrPackAdvExtIndPdu(pAdvSet, pAdvSet->advHdrBuf, FALSE);

Maybe I should close this bug and report another one? As this is different from the original report.

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 23, 2019

Maybe I should close this bug and report another one? As this is different from the original report.

Yes, I can see there is already separated report. I'll close this issue.

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