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

iic error NRF_ERROR_NO_MEM with app_sched_event_put

hi 

i want to use iic in my project ,and i add iic func to my project refrence project twi_sensor.

the code of iic like this:

	i2c_config_t iic_config=
	{
		.scl_pin = I2C_CLK_PIN,
		.sda_pin = I2C_SDA_PIN,
		.freq    = I2C_SPEED_400K,
	};
void am_app_i2c_init (i2c_config_t i2c_config)
{
    ret_code_t err_code;

		nrf_drv_twi_frequency_t fre_table[]=
		{
			NRF_DRV_TWI_FREQ_100K,
			NRF_DRV_TWI_FREQ_250K,
			NRF_DRV_TWI_FREQ_400K,
		};
	
    const nrf_drv_twi_config_t twi_config = {
       .scl                = i2c_config.scl_pin,
       .sda                = i2c_config.sda_pin,
       .frequency          = fre_table[i2c_config.freq],
       .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
       .clear_bus_init     = false
    };

    err_code = nrf_drv_twi_init(&m_twi, &twi_config, twi_handler, NULL);
    APP_ERROR_CHECK(err_code);

    nrf_drv_twi_enable(&m_twi);
}

void am_i2c_send_data(uint8_t addr,uint8_t const * p_data, uint8_t length, bool no_stop)
{
    ret_code_t err_code;

    err_code = nrf_drv_twi_tx(&m_twi, addr, p_data, length, no_stop);
    APP_ERROR_CHECK(err_code);
    while (m_xfer_done == false);

}

I call the api in the main 

	port_i2c_init();
		
	port_i2c_send(0xaa , data,  10);

then compile and download the hex to the chip,but the log show like this:

00> <error> app: ERROR 4 [NRF_ERROR_NO_MEM] at ..\..\..\..\..\..\components\libraries\timer\app_timer2.c:181
00> 
00> PC at: 0x0003817F

the code of app_timer2.c:181 is 

uint32_t err_code = app_sched_event_put(&timer_event,
sizeof(timer_event),
scheduled_timeout_handler);

some para like this:

#define NRF_QUEUE_ENABLED 1

#define SCHED_QUEUE_SIZE                    20                                         /**< Maximum number of events in the scheduler queue. */

i try change the  SCHED_QUEUE_SIZE   to 40 and change the ram ,it is  no effect. so what should i do to solve this problem ?

Parents Reply
  • i find the NRF_DRV_TWI_EVT_DONE of twi_handler can never comming by set the breakpoint be after "NRF_DRV_TWI_EVT_DONE:" in project twi_sensor, i try to comment the code "while (m_xfer_done == false);",it can work ,and i can see the wave by logic anlyzer:

    so,now my confuse is why the event NRF_DRV_TWI_EVT_DONE of twi_handler will not comming ?and there if any 

    potentially dangerous when send large data and the code comment "while (m_xfer_done == false)"?

Children
  • You will get a NRF_DRV_TWI_EVT_ADDRESS_NACK or NRF_DRV_TWI_EVT_DATA_NACK event instead of the NRF_DRV_TWI_EVT_DONE event if the sensor rejects the request. I guess the 'm_xfer_done' flag is not updated for those events?

    pipixia_8_8 said:
    potentially dangerous when send large data and the code comment "while (m_xfer_done == false)"?

    I think it's fine to use it as long as you handle the error events mentioned above. Otherwise, the program may end up getting stuck in the while loop as you have experienced. Anyway, here is another TWI example without the blocking while loops if you are interested https://devzone.nordicsemi.com/f/nordic-q-a/62494/nrf_drv_twi_rx-can-t-read-correct-data-but-always-only-zero

     

  • hi,thank for you reply,when i realize the problem of ack,connect to the iic device, and the iic work well.but now i try to send iic data in a timer handler,i open the  APP_SCHEDULER_ENABLED 1.  and i init the usb in my project.so i dont kown why i send the data in the timer handler will report 

    ERROR 4 [NRF_ERROR_NO_MEM] at ..\..\..\..\..\..\components\libraries\timer\app_timer2.c:181

    this is my code

    //扫描定时器回调
    void led_scan_timer_handler(void * p_context)
    {
    	disp_scan();
    	
    //stream_prase(stream_page.para,led_data);
    	
    }
    //定时器初始化
    void led_scan_timer_init(void)
    {
        
    	  ret_code_t err_code;
        err_code = app_timer_create(&m_led_scan_timer_id,
                                    APP_TIMER_MODE_REPEATED,
                                    led_scan_timer_handler);
        APP_ERROR_CHECK(err_code);
    }
    //启动定时器
    void led_scan_timer_start(void )
    {
        ret_code_t err_code;
    
        err_code = app_timer_start(m_led_scan_timer_id, LED_FLASH_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    
    }
    //关闭定时器
    void led_scan_timer_stop(void)
    {
        ret_code_t err_code;
    
        err_code = app_timer_stop(m_led_scan_timer_id);
        APP_ERROR_CHECK(err_code);
    }

    void am_i2c_send_data(uint8_t addr,uint8_t const * p_data, uint8_t length, bool no_stop)
    {
        ret_code_t err_code;
    	
        err_code = nrf_drv_twi_tx(&m_twi, addr, p_data, length, no_stop);
    //		iic_printf("err_code  == %d ",err_code);
        APP_ERROR_CHECK(err_code);
        while (m_xfer_done == false);	//没有器件调试的时候暂时不使用
    		m_xfer_done = false;
    		//while(err_code == NRF_ERROR_BUSY);//等待传输完成
    	
    
    }
    
    
    void port_i2c_send(uint8_t addr,uint8_t *p_data, uint8_t length)
    {
    	#if (SOC_TYPE ==NRF_52832)
    
    	#elif (SOC_TYPE ==NRF_52840)
    	
    	am_i2c_send_data( addr,  p_data,length, 0 );
    	
    		#else
    	#endif
    }

    void disp_scan(void)
    {
    	
    	uint8_t need_flash=0;
    	/*
    	if(!disp_control.valid)
    		return;
    	*/
    	
    	
    	//控制速度   显示间隔: 50+(101-speed)*10  ms
    	if(disp_control.time_count%(LED_MIN_INTERVAL_MS+LED_SCAN_BASE_MS*(100-disp_control.disp_page->speed))==0)
    	{
    		//数据解析
    		if(disp_control.disp_page->value_prase!=NULL)
    		{
    			need_flash = disp_control.disp_page->value_prase(disp_control.disp_page->para,led_data);
    		}
    		
    		
    		//定时器是否需要关闭
    		if(need_flash)
    		{
    			
    		}
    		else
    		{
    			led_scan_timer_stop();
    			//关闭定时器
    		}
    		
    		
    		//led 显示函数
    	//	disp_frame_data( led_data,disp_control.disp_page->lightness);
    		
    		
    		//for test
    		uint8_t data=0x20;
    		port_i2c_send(0x74 ,&data,  1);
    		
    	}
    }

  • i test the problem by code 

    		uint8_t data=0x20;
    		port_i2c_send(0x74 ,&data,  1);

    send iic data and report.what shuold i modify for this problem ?i guess mybe rtc config

  • Hi,

    The send function will become blocking if the 'm_xfer_done' flag for some reason is not getting cleared, and in that case, prevent the scheduler queue from being processed. To see if this could be the reason in this case, can you try to comment the "while (m_xfer_done == false)" line in the send function and see if the problem persists.

  • i know your means,and i try to do as you say, comment the "while (m_xfer_done == false)" will result in another problem,the twi have no enough time to send all the data before new send call comming.and it report

     00> <error> app: ERROR 17 [NRF_ERROR_BUSY] at ..\..\..\am_app\am_driver\I2C\am_app_i2c.c:79

     

    so if there is some way to avoid this problem ,for example,send the big data in the main loop?

Related