As a brief introduction, our research group uses bluetooth advertising to broadcast commands and responses between end devices and 'routers' which are connected to a PC.
As this mechanism is being used for commands, both 'end devices' and 'routers' need to switch between scanning and advertising when a command or response needs to be sent.
Taking the router as the more difficult case, we need to be scanning 100% of the time, except for when we wish to send a command, at which point an advertising packet/sequence should be sent as soon as possible.
The behaviour that would be ideal for us is that scan windows are preempted in order to send an advertisement, and at the end of the TX period the scanning resumes immediately.
The below image shows what we want to achieve:

Currently it looks like advertising waits until the end of a scan window before it is transmitted (tested by extending the scan interval and window to 5 seconds while trying to advertise).
The following image shows what we think is happening:

We can reduce the scan interval to ~100ms in order to get reasonably high throughput, but it is still not ideal.
Our system is talking directly to the soft device (no SDH layer), and the current configuration is the following.
/* Error handling ommitted for brevity */
uint8_t pucScanningData[NRF_BLE_SCAN_BUFFER];
void vScan(xBluetoothScanParameters_t *pxParams)
{
ble_gap_scan_params_t xScanParams = { 0 };
ble_data_t xScanningData;
/* Convert scan parameters from ms to function args */
/* 1 function unit is 0.625ms, which is 5/8, so multiply by 8/5 */
configASSERT( pxParams->usScanIntervalMs < 40960 );
configASSERT( pxParams->usScanWindowMs < 40960 );
usScanInterval = ( uint16_t )( ( (uint32_t) pxParams->usScanIntervalMs * 8 ) / 5 );
usScanWindow = ( uint16_t )( ( (uint32_t) pxParams->usScanWindowMs * 8 ) / 5 );
xScanParams.extended = 0;
xScanParams.report_incomplete_evts = 0;
xScanParams.active = pxParams->bActiveScanning;
xScanParams.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;
xScanParams.scan_phys = BLE_GAP_PHY_1MBPS;
xScanParams.interval = usScanInterval;
xScanParams.window = usScanWindow;
xScanParams.timeout = 0;
xScanningData.p_data = pucScanningData;
xScanningData.len = NRF_BLE_SCAN_BUFFER;
sd_ble_gap_scan_start( &xScanParams, &xScanningData );
}
void vAdvertise(xBluetoothAdvertiseParameters_t *pxParams )
{
uint8_t ucAdvertisingHandle;
uint16_t usAdvertisingInterval;
ble_gap_adv_data_t xAdvData = { 0 };
ble_gap_adv_params_t xAdvParams = { 0 };
/* Convert interval from ms to function args */
/* 1 function unit is 0.625ms, which is 5/8, so multiply by 8/5 */
usAdvertisingInterval = (uint16_t)( ( (uint32_t) pxParams->usAdvertisePeriodMs ) * 8 ) / 5;
xAdvParams.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
xAdvParams.properties.anonymous = 0;
xAdvParams.properties.include_tx_power = 0;
xAdvParams.p_peer_addr = NULL;
xAdvParams.interval = usAdvertisingInterval;
xAdvParams.duration = 0; // Rely on advertising count to terminate
xAdvParams.max_adv_evts = 1;
xAdvParams.filter_policy = BLE_GAP_ADV_FP_ANY;
xAdvParams.primary_phy = BLE_GAP_PHY_1MBPS;
xAdvData.adv_data.p_data = pxParams->pucData;
xAdvData.adv_data.len = pxParams->ucDataLen;
sd_ble_gap_adv_set_configure( &ucAdvertisingHandle, &xAdvData, &xAdvParams );
sd_ble_gap_adv_start( ucAdvertisingHandle, BLE_CONN_CFG_TAG_DEFAULT );
}
Is the preemptive behaviour possible to configure? This answer from several years ago said scanning blocks advertising, but things change.
https://devzone.nordicsemi.com/f/nordic-q-a/7003/advertising-scanning-problems
Also, has the following issue regarding lost scanning intervals been fixed? My testing suggests not, but maybe my config is wrong.
We are using nRF52840 devices, S140 v6.0, SDK 15.0
Cheers,
Jordan