This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

No preemption in application

Hi,

I use the peripheral ble_app_uart with nRF52832 (Murata module). The nRF52832 is connected to another MCU, STM32L476, via UART. 

I develop using IAR, with SDK V15.0.0

My problem is that the uart_event_handle is not preempted by ble_nus_on_ble_evt.

I set a flag in ble_nus_on_ble_evt and in uart_event_handle I wait for it to be set. If I wait in uart_event_handle the flag is not set (ble_nus_on_ble_evt never executes), but if I remove the while loop ble_nus_on_ble_evt executes.

the priority for both is the same as in the original ble_app_uart example (ble_nus_on_ble_evt has higher priority).

I even tried not using BLE_NUS_BLE_OBSERVER_PRIO (for ble_nus_on_ble_evt) and APP_IRQ_PRIORITY_LOWEST (for uart_event_handle), and use 2 and 7 respectively.

The code in uart_event_handle:

  switch (p_event->evt_type)
  {
    case APP_UART_DATA_READY:

      if (eCONNECTED_CONFIRMED == ox_conn_mode) // In Approved connection mode -> Pass the byte to the BLE
      {
        if (GetPacketFromWatch(&data_array, &index))
        {
          do
          {
            if (index > BLE_NUS_MAX_DATA_LEN)
            {
              length = BLE_NUS_MAX_DATA_LEN;
              index -= BLE_NUS_MAX_DATA_LEN;
                               f_ble_tx_complete = 0;
              err_code = ble_nus_data_send(&m_nus, &data_array.byte_data[out_index], &length, m_conn_handle);
              out_index += BLE_NUS_MAX_DATA_LEN;

              while(0 == f_ble_tx_complete);  //waiting here

The code in ble_nus_on_ble_evt:

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_nus, p_ble_evt);
            break;

        case BLE_GATTS_EVT_WRITE:
            on_write(p_nus, p_ble_evt);
            break;

        case BLE_GATTS_EVT_HVN_TX_COMPLETE:
            on_hvx_tx_complete(p_nus, p_ble_evt);
            f_ble_tx_complete = 1;
            break;

Parents
  • Hi,

     

    Both these handlers are executed in the NVIC interrupt priority 7, which is why your while-loop will never exit. I'd recommend that you schedule the ble_nus_data_send logic to main context instead.

     

    The define BLE_NUS_BLE_OBSERVER_PRIO will set the priority on which order each hook/callback will be called when polling the event from the softdevice_handler, but they all are still executed in handler context.

     

    Best regards,

    Håkon

Reply
  • Hi,

     

    Both these handlers are executed in the NVIC interrupt priority 7, which is why your while-loop will never exit. I'd recommend that you schedule the ble_nus_data_send logic to main context instead.

     

    The define BLE_NUS_BLE_OBSERVER_PRIO will set the priority on which order each hook/callback will be called when polling the event from the softdevice_handler, but they all are still executed in handler context.

     

    Best regards,

    Håkon

Children
  • Thanks.

    Actually, from what I've seen, they don't have the same priority,and as I said I tried forcing different priorities.

    I found the problem though, f_ble_tx_complete was initialized with 0 instead of 1, so the first transmission didn't occur. Regardless I moved the UART part to main.

  • I was mistaken, I moved the function from main to SWI, and there's no preemption.

    I changed in ble_stack_init the line to force priority = 2:

    NRF_SDH_BLE_OBSERVER(m_ble_observer, 2, ble_evt_handler, NULL);

    and I set SWI:

    nrf_drv_swi_alloc(&ble_uart_swi, ble_tx_swi_event_handler, APP_IRQ_PRIORITY_LOWEST);

    The SWI waits in a loop for a flag set in ble_evt_handler, but it never reaches it. the SWI executes ble_nus_data_send, then I expect the event BLE_GATTS_EVT_HVN_TX_COMPLETE to be triggered, but the program never reaches it since there's no preemption.

    If I move the function from SWI (and disable SWI) to main all functions properly.

Related