Can I user NRF TWI Manager to write varying lengths from a buffer?

Hello,

I am attempting to use the NRF twi manager based on the "twi master using nrf twi manager" example. I noticed that the example only reads and wrties a single byte and hence the transfer sizes can be defined as constants. However, I am trying to use an I2C uart module, since NRF52832 only has one UART, to output some debug information.

Hence the writes are of variable length and I am struggling to get the code to compile as it requires the transfer[x].length to be a constant. So my question is if I can use the manager to schedule these writes.

I have attempted to use the standard twi master which results in watchdog resets as the "while (m_xfer_done == false)" results in a blocking call even when using an event handler. I understand that I could implement a queuing mechanism however, I am trying to avoid that effort if the twi manager does this already.

Ankit

  •   thank you for the suggestion, I will try that. 

     I think the issue with resets has something to do with the app_timer. I have set it up in repeated mode to trigger every 1000 ms, however it always triggers every 1024 ms. Why would that be? I profiled the calls inside the timer and they barely take 2 ms. I also moved the twi tx to the main loop as you suggested and still noticed watchdog resets. I have added many debugging messages and the issue points to the timer not starting at all. 

    Which process could stop the timer from starting? I am using the nrf52 ble uart profile with SD enabled. Do note that this base code with SD enabled is working reliably in the field for over 2 years now, built against the same nRF SDK.

  • Hi,

    exsurgo_ankit said:
    I have set it up in repeated mode to trigger every 1000 ms, however it always triggers every 1024 ms

    How are you measuring this? I tried setting a repeated app timer timeout to 1000ms and toggled a GPIO in the callback handler and measured something much closer to 1000ms then 1024 ms. 

    exsurgo_ankit said:
    I have added many debugging messages and the issue points to the timer not starting at all. 
    exsurgo_ankit said:
    Which process could stop the timer from starting? I am using the nrf52 ble uart profile with SD enabled

    Is this another timer or that triggers the feeding of the watchdog? I'm a bit confused, above you mentioned that the app timer is triggered every 1024, can you elaborate.

    Also, it would be great if you could share a minimal example that reproduces this issue or at least share some relevant code in regards to the app timer. 

    regards

    Jared 

  • Hello Jared,


    I have RTC configured to trigger every 1 ms and that keeps track on milliseconds since startup. I use that variable to log(using RTT) when the timer is triggered.

    There is only one app timer which refreshes watchdog. The timer does various tasks. I log the ticks since startup at various points in the timer and it takes about 2 ms to complete.

    Here is some source code that show rtc and app timer. using RTT logger for some debug messages. There are more in the other files which tell me what happened last before a watchdog reset. Also the watchdog event handler is never triggered. I was hoping I could log the call stack in the watchdog handler and get to the root of the problem. Reason I know the timer is not triggered is because the RTT log at the start is never written. However the timer does end the operation every time based on the last RTT log statement.

    /** @brief: Function for handling the RTC0 interrupts.
     * Triggered on TICK and COMPARE0 match.
     */
    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {    
        (void) int_type;
        
        //increment 1m tick ctr
        g_ticks_since_startup++;    
    }
    
    /**
     * @brief Handler for timer events.
     * 
     * @param p_context 
     */
    static void timer_handler(void * p_context)
    {
        (void) p_context;
        NRF_LOG_RAW_INFO("Timer %d\n", g_ticks_since_startup);
        
        //feed the watchdog
        nrf_drv_wdt_channel_feed(m_channel_id);    
        
        
        //do more stuff
        
        //get uart sensor data 
        sensor_poll(&m_nus);
        NRF_LOG_RAW_INFO("Timer end %d,", g_ticks_since_startup);
       
        
        //set flush logs flag
        flush_pending_logs = true;
    }
    
    
    /**@brief Function for initializing the timer module.
     */
    static void timers_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_create(&m_timer, APP_TIMER_MODE_REPEATED, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = app_timer_start(m_timer, APP_TIMER_TICKS(1000), NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief WDT events handler.
     */
    void wdt_event_handler(void)
    {
        NRF_LOG_RAW_INFO("WDT trig\r\n");
        //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
    }
    
    int main(void)
    {
        /* Init systick driver */
        nrf_drv_systick_init();
    
        
        log_init();
        
        
        timers_init();
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();   
    
        //RTC Init
        lfclk_config();
        rtc_config();
        
        //feed the watchdog
        nrf_drv_wdt_channel_feed(m_channel_id);
          
        gpio_init();      
        
        //uart sensor init
        sensor_init();
    
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
        
        //set the ble tx power
        sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_SCAN_INIT, BLE_CONN_HANDLE_INVALID, BLE_TX_POWER); 
        APP_ERROR_CHECK(err_code);
        
        // Start advertising.        
        advertising_start();
    
        //initalise the local adc for battery voltage monitoring   
        saadc_init();
        
        //init the temperature sensor
        g_mc_termperature = 0;
            
        // Enter main loop.
        for (;;)
        {
            // Clear the event register.
            __SEV();
            __WFE();
            // Wait for an event.
            __WFE();
            
            if(flush_pending_logs)
            {
                //flush logs
                flush_pending_logs = false;
            }
    
            idle_state_handle();    
        }
    }

  • Hi,

    Could you share your sdk_config.h file as well?

    regards

    Jared 

  • Hello Jared,

    Here is the link to the sdk_config.h

    https://www.dropbox.com/s/n4s5zc5hb13317g/sdk_config.h?dl=0

    Also, I have figured out the cause of watchdog reset and fixed that. The timer delay from 1000 to 1024 ms still baffles me.

    Regards

Related