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

Inserting extra codes in ble_uart_app

I was trying to develop a project using nrf51822. Which needs to send data over ble and do some functions according to the data received. In which I have to add a lengthy code for my application. Which has to use pstorage, pwm, etc. The main function of ble_app_uart ends like this. for (;;) { power_manage(); }

My question is how can I include my codes in this main file without hurting ble_uart functionality. I tried by simply adding my codes after power mange() function, but it didn't work because that wil put the cpu into sleep mode and it will not execute my code. Then I commented the power_ manage function, but that time I couldn't send data from nrf uart app. The app is not getting connected with the device. What should I do to achieve this thing? Please give me guidelines.

  • Hi

    Perhaps the current consumption guide, section "Low power mode with BLE softdevice" can give some basic understanding on how the power_manage function works.

    When including pwm, you need to initialize the pwm module in a similar way as done in the pwm example in the SDK. Same applies for the pstorage module.

    The BLE stuff works autonomously in the background to maintain the connection, and when you send data over BLE via the UART service, i.e. by calling the ble_nus_string_send, then the data is pushed to the softdevice and sent over BLE.

    When you have initialized e.g. PWM, it is generated with a timer+ppi+GPIOTE peripherals, and does not use CPU unless you change the duty cycle

    BLE operation has highest priority for the CPU, so whenever there is BLE activity and the CPU is needed, any ongoing CPU activity is preempted, and will again continue after the BLE operation is done. This is done with priorities, where everything executed in the main context, i.e. in the main function, has the lowest priority. More on priorities here (1) (2) (3).

    Update 23.10.2015 Whether to put your custom code in the main function or in an interrupt handler is your design decision.

    When the program starts, it will execute the main function and then the CPU is disabled (enters System On low power mode) when sd_app_event_wait (power_manage) is called. The CPU will be sleeping until an interrupt occurs, then the CPU executes the interupt and then execution returns to the main function and starts by executing the code following sd_app_event_wait. Since sd_app_event_wait is in the main loop, then sd_app_event_wait will soon be executed again, making the CPU enter sleep mode until another interrupt occurs.

    • If you place your code in the main loop, it will be executed on every interrupt, no matter what interrupt it is.
    • If you place your code into the main function outside of the main loop it will be executed at startup and only once
    • If you place your code into an interrupt handler, then your code is executed only on the specific interrupt that triggers that handler.

    There are three types of interrupts or events:

    • Peripheral events. These are for example TIMER, RTC, ADC, SPI, UART, TWI peripherals, which is actual hardware on the nrf51, see different chapters in the nRF51 Series Reference Manual.

    • Softdevice events. Those are received from the softdevice. These are in fact devided into two groups, BLE interrupts and System interrupts. BLE interrupts have their source from BLE communication with a peer device, because of a BLE message received or sent, etc. System interrupts are generated by the softdevice to notify the application of some activity that is not caused by BLE communication, e.g. to notify the application of a completed flash operation, notify the application of the high frequency crystal has started, etc. You register for BLE events and system events by calling

        softdevice_ble_evt_handler_set(ble_evt_dispatch);
      

      and

        softdevice_sys_evt_handler_set(sys_evt_dispatch);
      

      as done in the ble_stack_init function in most of the BLE examples in the nRF51 SDK.

    • Module events. There are different software modules available in the nRF51 SDK that you use to perform different tasks. For example, there is an advertising module, pstorage module to write to flash, UART module (or UART driver) to use the UART peripheral, etc. For the software modules, you usually register an event handler when initializing the module, and implement the event handler in your application. The event handler is then called from the module. E.g. for the app_uart module, you call APP_UART_FIFO_INIT in you application to initialize the UART and specify the uart_init_handle as the event handler for the app_uart module. The app_uart module will then call the uart_init_handle when data is received in the UART peripheral.

    So where to place your code:

    • If you want to forward received BLE nus (Nordic UART Service) data to the hardware UART, then you call app_uart_put in the nus_data_handler, as done in the ble_app_uart example.
    • If you want to change the waveform periodically of your PWM, then you start a timer and change the waveform in the timer event handler. You could obtain the same by changing the waveform in the main loop and also call i.e. nrf_delay_us function to change the PWM waveform with the correct frequency, but that is not a good practice as that will block the CPU and prevent it from doing anything else meanwhile.

    The best practice is actually:

    • You have short code to execute -> you can place your code in an interrupt handler
    • You have long code to execute. If you execute a long code in an interrupt handler, then it will block other interrupts that have same or lower priority, so that is not a good practice. A good practice is to trigger execution in an event handler, but execute the code itself in the main context. You can e.g. use the scheduler to do this, i.e. call app_sched_event_put() in the event handler.
  • Thanks for the reply. But, how do I make it to run my application code with ble uart, should I use interrupts for that instead of doing it in main function

Related