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

Trigger saadc sample task with ppi on a ble rscs profile

Hi everyone,

Maybe my problem has already been solved in another discussion, if so, I haven't found it yet !

I'm programming on a external board using nrf52832.

I'm developping a program based on the ble_app_rscs_ example of the SDK 14.2.

I'm trying to add saadc triggered by ppi as in the example of the SDK (peripheral -> saadc)

Here is my problem, where I try to trigger the saadc with ppi, the application get stucked and do not advertise.

But when I trigger the saadc manualy with nrf_drv_saadc_sample(), and remove those two lines :

saadc_sampling_event_init();
saadc_sampling_event_enable();  

it works just fine !

So the problem comes from those two functions.

Here is my main function :

/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds;

    //led init
    nrf_gpio_cfg_output(12);
    nrf_gpio_cfg_output(15);
    nrf_gpio_cfg_output(17);
    
    nrf_gpio_pin_set(12);     //Green led ON
    nrf_gpio_pin_set(15);       //Blue led OFF
    nrf_gpio_pin_set(17);       //Red led OFF

    
    // Initialize.
    log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    ble_stack_init();
    gap_params_init();
    gatt_init();
    advertising_init();
    services_init();
    sensor_simulator_init();
    conn_params_init();
    peer_manager_init();

    //Initialize the TWI connection
    twi_init();
    fn_configure_LIS2DH_accelero();

    //Initialize the SAADC
    saadc_init();
    saadc_sampling_event_init();
    saadc_sampling_event_enable();  

    // Start execution.
    NRF_LOG_INFO("Running Speed and Cadence example started.");
    application_timers_start();

    advertising_start(erase_bonds);

    // Enter main loop.
    for (;;)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            power_manage();
        }
    }
}

I use the same saadc functions as in the nordic saadc example :

//SAADC
void timer_handler(nrf_timer_event_t event_type, void * p_context)
{
  
}

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 400ms */
		uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 40);	//Oliver : Sampling rate = 2,5Hz
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}


void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);

    APP_ERROR_CHECK(err_code);
}


void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
        
        
        my_saadc_value = p_event->data.done.p_buffer[0];
    }
}

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7); //NRF_SAADC_INPUT_AIN3); //FB NRF_SAADC_INPUT_AIN0);
    
    channel_config.gain = NRF_SAADC_GAIN2;              //FB change gain from 1/6 (default) to 2

    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

}

And I've included as in the saadc example : 

//SAADC
#define SAMPLES_IN_BUFFER 1
volatile uint8_t state = 1;

static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(1);
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t     m_ppi_channel;
//static uint32_t              m_adc_evt_counter;
nrf_saadc_value_t my_saadc_value = 0;

I've modified the sdk_config.h file in order to enable the saadc, the nrf_drv_timer1 and the ppi function.

So i don't understand wher the problem is, I suspect it to be in the ppi...

Can someone help me to solve the problem ?

Thank you,

Regards,

Olivier

Parents
  • Hi,

    Do you know where your code is stuck? It may have ended up in an endless while loop in an error handler. Have you tried debugging like this?

  • I'm using Segger, but anyway, I'm following the step by step debug routine explained in the post.

    So went to the definition of APP_ERROR_CHECK() which calls APP_ERROR_HANDLER().

    I went to the definition of APP_ERROR_HANDLER() which calls  app_error_handler().

    I wanted to go to the definition of app_error_handler() but it says "Can't find symbol".

    So maybe I did not include the right module ?

    I've included app_error.c as in the example of nordic.

    Here is the definition of APP_ERROR_CHEK()

    #include <stdint.h>
    #include <string.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_err.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_bas.h"
    #include "ble_rscs.h"
    #include "ble_dis.h"
    #include "ble_conn_params.h"
    #include "sensorsim.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "peer_manager.h"
    #include "bsp_btn_ble.h"
    #include "fds.h"
    #include "ble_conn_state.h"
    #include "nrf_ble_gatt.h"
    
    //accelerometer
    #include "nrf_drv_twi.h"
    #include "boards.h"
    #include "app_util_platform.h"
    
    //saadc
    #include "nrf_drv_timer.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    
    
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"

    and here are my includes :

    /**@brief Macro for calling error handler function.
     *
     * @param[in] ERR_CODE Error code supplied to the error handler.
     */
    #ifdef DEBUG
    #define APP_ERROR_HANDLER(ERR_CODE)                                    \
        do                                                                 \
        {                                                                  \
            app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__);  \
        } while (0)
    #else
    #define APP_ERROR_HANDLER(ERR_CODE)                                    \
        do                                                                 \
        {                                                                  \
            app_error_handler_bare((ERR_CODE));                            \
        } while (0)
    #endif
    /**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS.
     *
     * @param[in] ERR_CODE Error code supplied to the error handler.
     */
    #define APP_ERROR_CHECK(ERR_CODE)                           \
        do                                                      \
        {                                                       \
            const uint32_t LOCAL_ERR_CODE = (ERR_CODE);         \
            if (LOCAL_ERR_CODE != NRF_SUCCESS)                  \
            {                                                   \
                APP_ERROR_HANDLER(LOCAL_ERR_CODE);              \
            }                                                   \
        } while (0)

    Thanks for your response !

    Olivier

  • It's ok, my bad, I have found app_error_handler()

    So the app_error_handler lokks like this : 

    /*lint -save -e14 */
    void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
    {
        error_info_t error_info =
        {
            .line_num    = line_num,
            .p_file_name = p_file_name,
            .err_code    = error_code,
        };
        while(1);
        app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
    
        UNUSED_VARIABLE(error_info);
    }

    I just added the "while(1);" loop in order to follow the post you send me.

    So I debug the code and it stopped in the app_error_fault_handler() : 

    __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
        NRF_LOG_FINAL_FLUSH();
    
    #ifndef DEBUG
        NRF_LOG_ERROR("Fatal error");
    #else
        switch (id)
        {
    #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
            case NRF_FAULT_ID_SD_ASSERT:
                NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED");
                break;
            case NRF_FAULT_ID_APP_MEMACC:
                NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS");
                break;
    #endif
            case NRF_FAULT_ID_SDK_ASSERT:
            {
                assert_info_t * p_info = (assert_info_t *)info;
                NRF_LOG_ERROR("ASSERTION FAILED at %s:%u",
                              p_info->p_file_name,
                              p_info->line_num);
                break;
            }
            case NRF_FAULT_ID_SDK_ERROR:
            {
                error_info_t * p_info = (error_info_t *)info;
                NRF_LOG_ERROR("ERROR %u [%s] at %s:%u",
                              p_info->err_code,
                              nrf_strerror_get(p_info->err_code),
                              p_info->p_file_name,
                              p_info->line_num);
                break;
            }
            default:
                NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc);
                break;
        }
    #endif
    
        NRF_BREAKPOINT_COND;
        // On assert, the system can only recover with a reset.
    
    #ifndef DEBUG
        NRF_LOG_WARNING("System reset");
        NVIC_SystemReset();
    #else
        app_error_save_and_stop(id, pc, info);
    #endif // DEBUG
    }
    
    /*lint -restore */

    at this line : 

    NRF_BREAKPOINT_COND;

    my screen looks like this : 

    Thanks for your help,

    Olivier

Reply
  • It's ok, my bad, I have found app_error_handler()

    So the app_error_handler lokks like this : 

    /*lint -save -e14 */
    void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
    {
        error_info_t error_info =
        {
            .line_num    = line_num,
            .p_file_name = p_file_name,
            .err_code    = error_code,
        };
        while(1);
        app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
    
        UNUSED_VARIABLE(error_info);
    }

    I just added the "while(1);" loop in order to follow the post you send me.

    So I debug the code and it stopped in the app_error_fault_handler() : 

    __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
        NRF_LOG_FINAL_FLUSH();
    
    #ifndef DEBUG
        NRF_LOG_ERROR("Fatal error");
    #else
        switch (id)
        {
    #if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
            case NRF_FAULT_ID_SD_ASSERT:
                NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED");
                break;
            case NRF_FAULT_ID_APP_MEMACC:
                NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS");
                break;
    #endif
            case NRF_FAULT_ID_SDK_ASSERT:
            {
                assert_info_t * p_info = (assert_info_t *)info;
                NRF_LOG_ERROR("ASSERTION FAILED at %s:%u",
                              p_info->p_file_name,
                              p_info->line_num);
                break;
            }
            case NRF_FAULT_ID_SDK_ERROR:
            {
                error_info_t * p_info = (error_info_t *)info;
                NRF_LOG_ERROR("ERROR %u [%s] at %s:%u",
                              p_info->err_code,
                              nrf_strerror_get(p_info->err_code),
                              p_info->p_file_name,
                              p_info->line_num);
                break;
            }
            default:
                NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc);
                break;
        }
    #endif
    
        NRF_BREAKPOINT_COND;
        // On assert, the system can only recover with a reset.
    
    #ifndef DEBUG
        NRF_LOG_WARNING("System reset");
        NVIC_SystemReset();
    #else
        app_error_save_and_stop(id, pc, info);
    #endif // DEBUG
    }
    
    /*lint -restore */

    at this line : 

    NRF_BREAKPOINT_COND;

    my screen looks like this : 

    Thanks for your help,

    Olivier

Children
  • So I tried to debug the program and... it worked !

    I just don't understand what the problem was, so now it works as I wanted to, although I didn't change anything !

    Thanks for the support,

    Olivier

  • Glad it worked. It is hard to say why it would suddenly work like that though. I usually modify the weak error handler like this to make it print out the information to a terminal when something asserts:

    __WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
    {
        static error_info_t  * p_error_info;
        p_error_info = (error_info_t*)info;
        NRF_LOG_ERROR("Error: ID: %d, PC: 0x%X\n\r", id, pc);
        NRF_LOG_ERROR("Error: Code: 0x%04X (%d), Line: %d, File: %s\n\r", p_error_info->err_code, p_error_info->err_code, p_error_info->line_num, (uint32_t)p_error_info->p_file_name);
        NRF_LOG_FINAL_FLUSH();
        ...
        ...

Related