hi,i want to control a led driver by frequency send iic data, i need send 600 bytles once at least 10ms each time ,and the 600 bytles send by 3times.send the 600 bytles need 24ms.i create a 10ms once timer,and in the end of the timer handler start the timer again.but now i find after run few mins the seeger will report the error:
00> <error> app: ERROR 4 [NRF_ERROR_NO_MEM] at ..\..\..\..\..\..\components\libraries\timer\app_timer2.c:181
and the chip cant work before reset.
at frist i guess the reson is the time of execute the 10ms timer handler is so long(24ms) that reslut in the scheduler problem.but when try to replace the iic send api to nrf_delay_ms( 24); the problem will not occur.so it is obvious that the reson is the iic send action.
this is my code
//扫描定时器回调 void led_scan_timer_handler(void * p_context) { UNUSED_PARAMETER(p_context); disp_scan(); // led_test(); //stream_prase(stream_page.para,led_data); } //定时器初始化 void led_scan_timer_init(void) { ret_code_t err_code; /* err_code = app_timer_init(); APP_ERROR_CHECK(err_code); */ err_code = app_timer_create(&m_led_scan_timer_id, APP_TIMER_MODE_SINGLE_SHOT, 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); }
disp_frame_data() in the disp_scan() is my iic send api
//led显示扫描函数 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 SCAN_DEBUG //数据解析 if(disp_control.disp_page->value_prase!=NULL) { need_flash = disp_control.disp_page->value_prase(disp_control.disp_page->para,led_data); // stream_prase(stream_page.para, led_data); } //定时器是否需要关闭 if(need_flash) { } else { led_scan_timer_stop(); //关闭定时器 } //led 显示函数 disp_frame_data( led_data,/*disp_control.disp_page->lightness*/10); //port_delay_ms(24); send_flag = 1; #endif } //触发延时动作 if(disp_control.time_count == disp_control.disp_page->delay_ms/LED_SCAN_BASE_MS)// { if(disp_control.disp_page->action!=NULL) { disp_control.disp_page->action(); } } #if 1 //用于某个插入界面只显示一段时间 if(disp_control.disp_page->show_ms==AWLAYS_LIGHTING)//常亮 { } else { if(disp_control.time_count == disp_control.disp_page->show_ms/LED_SCAN_BASE_MS)//定时显示 { stop_led_show(); if(ExistPushPage)//退出插入界面 { ExistPushPage = 0; //重新进入之前的界面 cmd_exit_push(NULL , NULL); } } } #endif disp_control.time_count++; if(disp_control.time_count%10) { NRF_LOG_INFO("disp_scan disp_control.time_count =%d\r\n",disp_control.time_count); } led_scan_timer_start( );//由于led的iic显示需要耗费大约30ms,所以不适用周期性毫秒定时器,采用接力方式完成,更为稳妥和保险 }
void disp_frame_data(uint8_t (*led_data)[RGB_LED_X_NUM][3],uint8_t lightness_per) { frame_data_to_chip( led_data); disp_one_chip_data( AW_CHIP_INDEX_0, chip0_data,lightness_per); disp_one_chip_data( AW_CHIP_INDEX_1, chip1_data,lightness_per); disp_one_chip_data( AW_CHIP_INDEX_2, chip2_data,lightness_per); } static void disp_one_chip_data(uint8_t device_index,uint8_t *pwm_data,uint8_t brightness) { static uint8_t last_brightness[AW_CHIP_MAX_NUM] ={0}; if(last_brightness[device_index]!=brightness) { set_chip_led_brightness( chip_table[device_index], brightness); } set_led_pwm_brightness(chip_table[device_index], pwm_data); last_brightness[device_index] = brightness; } void set_led_pwm_brightness(uint8_t device_addr,uint8_t *pwm_data) { set_page(device_addr, AW20216_REG_PAGE1); memcpy(&page_data[1],pwm_data,216); page_data[0] = PWM_REG_START_ADDR; aw_iic_writebytes(device_addr,page_data,216); } void iic_writebytes(uint8_t device_addr,uint8_t *data,uint8_t len) { port_i2c_send( device_addr,data,len+1); } 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 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); m_xfer_done = false; }
when i comment the code
disp_frame_data( led_data,/*disp_control.disp_page->lightness*/10);
and replace by the code
port_delay_ms(24); void port_delay_ms(uint32_t ms) { #if (SOC_TYPE ==NRF_52832) nrf_delay_ms( ms ); #elif (SOC_TYPE ==NRF_52840) nrf_delay_ms( ms ); #endif }
the problem will not occur.
so i dont konw if the twi cant send data frequency ? and what should i do to slove this problem?