Btnm cause my hardware reset

Description

I tried to design a custom btnm, it’s similar to our daily keyboard like “CapsLK” function and so on, but when I changed the map of btnm, some of expected sequence caused my hardware reset,.See the code below, “Up” “Down” btn is OK to change, but “Num” and “FU” btn caused my hardware reset.

What MCU/Processor/Board and compiler are you using?

RDA borad.

What do you want to achieve?

Design a keyboard as we use daily on mobile phone.

What have you tried so far?

I tried to replace the btnm map with the previously one and that two btn works, so I guess this matter with the content of btnm map, but I don’t know why.

Code to reproduce

/*You code here*/
void temp_btnm_test()
{
	static lv_style_t cont_style;
	lv_style_copy(&cont_style, &lv_style_pretty_color);
	cont_style.body.padding.left = 0;
	cont_style.body.padding.right = 0;
	cont_style.body.padding.top = 0;
	cont_style.body.padding.bottom = 0;
	cont_style.body.padding.inner = 0;
	cont_style.body.radius = 0;
	cont_style.body.border.width = 0;
	cont_style.body.border.color = LV_COLOR_RED;
	cont_style.body.main_color = LV_COLOR_RED;
	//cont_style.body.opa = LV_OPA_TRANSP;

	lv_obj_t*content_cont = lv_cont_create(lv_scr_act(NULL), NULL);
	lv_obj_set_pos(content_cont, 0, 50);//40
	lv_cont_set_fit(content_cont, LV_FIT_NONE);
	lv_cont_set_layout(content_cont, LV_LAYOUT_OFF);
	lv_cont_set_style(content_cont, LV_CONT_STYLE_MAIN, &cont_style);
	lv_obj_set_size(content_cont, 480, 200);
	//account and password
	static lv_style_t click_btn_style;
	lv_style_copy(&click_btn_style, &lv_style_btn_rel);
	click_btn_style.body.opa = LV_OPA_TRANSP;

	lv_obj_t *label_1, *label_2, *btn_account, *btn_password;
	label_1 = lv_label_create(content_cont, NULL);
	lv_obj_align(label_1, NULL, LV_ALIGN_IN_TOP_LEFT, 100, 20);
	lv_label_set_text(label_1, "Account:");

	label_2 = lv_label_create(content_cont, NULL);
	lv_obj_align(label_2, label_1, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 70);
	lv_label_set_text(label_2, "Password:");
	//account
	lv_obj_t * obj_ta = lv_ta_create(content_cont, NULL);
	lv_obj_align(obj_ta, label_1, LV_ALIGN_OUT_RIGHT_TOP, 10, -5);
	lv_obj_set_size(obj_ta, 150, 50);
	account_ta[0] = obj_ta;
	lv_ta_set_one_line(obj_ta, true);
	lv_ta_set_text(obj_ta, "");
	lv_ta_set_placeholder_text(obj_ta, "please insert");

	btn_account = lv_btn_create(content_cont, NULL);
	lv_obj_align(btn_account, label_1, LV_ALIGN_OUT_RIGHT_TOP, 10, -5);
	lv_btn_set_layout(btn_account, LV_LAYOUT_OFF);
	lv_obj_set_size(btn_account, 240, 50);
	lv_btn_set_style(btn_account, LV_BTN_STYLE_REL, &click_btn_style);
	lv_obj_set_event_cb(btn_account, Account_insert);
	//password  
	obj_ta = lv_ta_create(content_cont, NULL);
	lv_obj_align(obj_ta, label_2, LV_ALIGN_OUT_RIGHT_TOP, 10, -5);
	lv_obj_set_size(obj_ta, 150, 50);
	account_ta[1] = obj_ta;
	lv_ta_set_text(obj_ta, "");
	lv_ta_set_placeholder_text(obj_ta, "please insert");

	btn_password = lv_btn_create(content_cont, NULL);
	lv_obj_align(btn_password, label_2, LV_ALIGN_OUT_RIGHT_TOP, 10, -5);
	lv_btn_set_layout(btn_password, LV_LAYOUT_OFF);
	lv_obj_set_size(btn_password, 240, 50);
	lv_btn_set_style(btn_password, LV_BTN_STYLE_REL, &click_btn_style);

static void Account_insert(lv_obj_t *btn, lv_event_t event)
{
	if (event == LV_EVENT_CLICKED) {
		lv_obj_t *got_parent, *got_child;
		got_parent = lv_obj_get_parent(btn);
		got_child = lv_obj_get_child(got_parent, btn);  //supposed to be text area match to btn
		Account_keyboard_create(got_child);
		lv_obj_set_hidden(btn, true);
	}
}

static void Account_keyboard_create(lv_obj_t* match_ta)
{
	static const char * btnm_map[] = { "q","w","e","r","t","y","u","i","o","p","\n",
									   "a","s","d","f","g","h","j","k","l","\n",
									   "Up","z","x","c","v","b","n","m","del","\n",
									   "Num","FU",","," ",".","*",""
									 };
	static lv_style_t style_btnm_bg;
	lv_style_copy(&style_btnm_bg, &lv_style_pretty);
	style_btnm_bg.body.radius = 0;
	style_btnm_bg.body.padding.inner = 5;
	style_btnm_bg.body.main_color = LV_COLOR_GRAY;
	style_btnm_bg.body.grad_color = LV_COLOR_GRAY;
	style_btnm_bg.text.color = LV_COLOR_WHITE;
	style_btnm_bg.body.padding.top = 2;
	style_btnm_bg.body.padding.bottom = 2;

	lv_obj_t *obj_kb = lv_btnm_create(lv_scr_act(), NULL);
	//lv_obj_set_size(obj_kb, scr_r_width, 200);
	lv_obj_set_width(obj_kb, scr_r_width);
	lv_btnm_set_map(obj_kb, btnm_map);
	lv_obj_align(obj_kb, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
	lv_btnm_set_style(obj_kb, LV_BTNM_STYLE_BG, &style_btnm_bg);

	lv_obj_set_event_cb(obj_kb, keyboard_event_handle);
}

static void keyboard_event_handle(lv_obj_t * obj, lv_event_t event)
{
	lv_obj_t *got_parent, *got_child;
	static const char * btnm_map_lower [] = { "q","w","e","r","t","y","u","i","o","p","\n",
									   "a","s","d","f","g","h","j","k","l","\n",
									   "Up","z","x","c","v","b","n","m","del","\n",
									   "Num","FU",","," ",".","*",""
	};

	static const char * btnm_map_caps[] = { "Q","W","E","R","T","Y","Y","I","O","P","\n",
									   "A","S","D","F","G","H","J","K","L","\n",
									   "Down","Z","X","C","V","B","N","M","del","\n",
									   "Num","FU",","," ",".","*",""
	};

	static const char * btnm_map_nums[] = { "+","1","2","3","del","\n",
		                                    "-","4","5","6","*","\n",
		"/","7","8","9","@","\n", 
		":",",","0",".","Bak",""
	};

	static const char * btnm_map_character[] = {",",".","?","!","<","\n",
		                                        ":",";","~","/",">","\n",
		                                       "@","#","$","%","=","\n",
		                                       //"*","(",")","-","+",
		                                       ""

	};

	char * btnm_control[] = {"del","Up","Down","Num","Bak","FU"};
	if (event == LV_EVENT_VALUE_CHANGED) {
		const char * txt = lv_btnm_get_active_btn_text(obj);
		if (txt == btnm_control[0]) { //del
			lv_ta_del_char(account_ta[0]);
		}
		else if (txt == btnm_control[1]) { //Up
			lv_btnm_set_map(obj, btnm_map_caps);//btnm_map_caps
		}
		else if (txt == btnm_control[2]) { //Down
			lv_btnm_set_map(obj, btnm_map_lower);
		}
		else if (txt == btnm_control[3]) { //Num
			lv_btnm_set_map(obj, btnm_map_nums);
		}
		else if (txt == btnm_control[4]) { //return
			lv_btnm_set_map(obj, btnm_map_lower);
		}
		else if (txt == btnm_control[5]) {
			lv_btnm_set_map(obj, btnm_map_character);
		}
		else {
			lv_ta_add_text(account_ta[0], txt);
		}
	}
}
}

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Click “Account” btn first to show btnm, and then click “Num” or “FU”, only thoes two btns cause reset. And I’m using version 6.0.

Can you upgrade to 6.1 and see if the problem is fixed there? You can use the release/v6 branch on GitHub. As far as I know there shouldn’t be any API breakage.

I tried to create a container to contain the btnm this time, and in the callback of btnm, I clean the children(btnm actually) of container and then recreate a new btnm in this coniner, just looks like this:(in the function of keyboard_event_handle)
else if (txt == btnm_control[2]) { //Down
//lv_btnm_set_map(obj, btnm_map_lower);
lv_obj_clean(keyboard_cont);

		lv_obj_t *obj_kb = lv_btnm_create(keyboard_cont, NULL);//lv_scr_act()
		lv_obj_set_width(obj_kb, scr_r_width);
		lv_btnm_set_map(obj_kb, btnm_map_lower);
		lv_obj_set_event_cb(obj_kb, keyboard_event_handle);
	}
	else if (txt == btnm_control[3]) { //Num
		lv_obj_clean(keyboard_cont);

		lv_obj_t *obj_kb = lv_btnm_create(keyboard_cont, NULL);//lv_scr_act()
		lv_obj_set_width(obj_kb, scr_r_width);
		lv_btnm_set_map(obj_kb, btnm_map_nums);
		lv_obj_set_event_cb(obj_kb, keyboard_event_handle);
	}

this works ok, so I am curious about why the before one happened, can’t it repeately set bntm map with “lv_btnm_set_map”?

Dynamic changing the map should work.

Can you try simply creating a button matrix and immediately set a few different maps?

I’ve tested in v7 like this. Does it work for you?


lv_obj_t * ta1;
static void keyboard_event_handle(lv_obj_t * obj, lv_event_t event);

static void Account_keyboard_create(lv_obj_t* match_ta)
{
    static const char * btnm_map[] = { "q","w","e","r","t","y","u","i","o","p","\n",
                                       "a","s","d","f","g","h","j","k","l","\n",
                                       "Up","z","x","c","v","b","n","m","del","\n",
                                       "Num","FU",","," ",".","*",""
                                     };

    lv_obj_t *obj_kb = lv_btnmatrix_create(lv_scr_act(), NULL);
    lv_obj_set_width(obj_kb, 500);
    lv_btnmatrix_set_map(obj_kb, btnm_map);
    lv_obj_align(obj_kb, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);

    lv_obj_set_event_cb(obj_kb, keyboard_event_handle);
}

static void keyboard_event_handle(lv_obj_t * obj, lv_event_t event)
{
    static const char * btnm_map_lower [] = { "q","w","e","r","t","y","u","i","o","p","\n",
                                       "a","s","d","f","g","h","j","k","l","\n",
                                       "Up","z","x","c","v","b","n","m","del","\n",
                                       "Num","FU",","," ",".","*",""
    };

    static const char * btnm_map_caps[] = { "Q","W","E","R","T","Y","Y","I","O","P","\n",
                                       "A","S","D","F","G","H","J","K","L","\n",
                                       "Down","Z","X","C","V","B","N","M","del","\n",
                                       "Num","FU",","," ",".","*",""
    };

    static const char * btnm_map_nums[] = { "+","1","2","3","del","\n",
                                            "-","4","5","6","*","\n",
        "/","7","8","9","@","\n",
        ":",",","0",".","Bak",""
    };

    static const char * btnm_map_character[] = {",",".","?","!","<","\n",
                                                ":",";","~","/",">","\n",
                                               "@","#","$","%","=","\n",
                                               "*","(",")","-","+",
                                               ""

    };

    char * btnm_control[] = {"del","Up","Down","Num","Bak","FU"};
    if (event == LV_EVENT_VALUE_CHANGED) {
        const char * txt = lv_btnmatrix_get_active_btn_text(obj);
        if (txt == btnm_control[0]) { //del
            lv_textarea_del_char(ta1);
        }
        else if (txt == btnm_control[1]) { //Up
            lv_btnmatrix_set_map(obj, btnm_map_caps);//btnm_map_caps
        }
        else if (txt == btnm_control[2]) { //Down
            lv_btnmatrix_set_map(obj, btnm_map_lower);
        }
        else if (txt == btnm_control[3]) { //Num
            lv_btnmatrix_set_map(obj, btnm_map_nums);
        }
        else if (txt == btnm_control[4]) { //return
            lv_btnmatrix_set_map(obj, btnm_map_lower);
        }
        else if (txt == btnm_control[5]) {
            lv_btnmatrix_set_map(obj, btnm_map_character);
        }
        else {
            lv_textarea_add_text(ta1, txt);
        }
    }
}
  ta1 = lv_textarea_create(lv_scr_act(), NULL);
  Account_keyboard_create(ta1);

I have tested that before, and this time I did it again, still got the same problenm, “Num” and “FU” btn can’t be clicked or system crash, the “cmd” give the error info,posted below, seems something about NULL POINTER.


I also traced the break for stop point, it shows below but I haven’t had a deep look of how this system running so I’m not quite understand how would this be triggered, guess some unintentional operation, maybe you would know more about this.

And I truly found something, I saw the descibitond of function "lv_btnm_get_active_btn_text” says:get the
last “activitated” btn(pressed,released), so will this send two “event” by one pressed(one released auto)?
To test this, I defined a bool variable and every time of “changed control” btn setting it as true, and break out next “event funtion”, it works if firstly press “Up” btn, still crash if firstly press “Num”,“Fu” btn.
BTW, firstly pressed “Up” btn, it will cha
Code here:

bool check_threshold = false;
static void keyboard_event_handle_1(lv_obj_t * obj, lv_event_t event)
{
if (check_threshold == true) {
check_threshold = false;
return;
}
static const char * btnm_map_lower[] = { “q”,“w”,“e”,“r”,“t”,“y”,“u”,“i”,“o”,“p”,"\n",
“a”,“s”,“d”,“f”,“g”,“h”,“j”,“k”,“l”,"\n",
“Up”,“z”,“x”,“c”,“v”,“b”,“n”,“m”,“del”,"\n",
“Num”,“FU”,","," “,”.","*",""
};

static const char * btnm_map_caps[] = { "Q","W","E","R","T","Y","Y","I","O","P","\n",
								   "A","S","D","F","G","H","J","K","L","\n",
								   "Down","Z","X","C","V","B","N","M","del","\n",
								   "Num","FU",","," ",".","*",""
};

static const char * btnm_map_nums[] = { "+","1","2","3","del","\n",
										"-","4","5","6","*","\n",
	"/","7","8","9","@","\n",
	":",",","0",".","Bak",""
};

static const char * btnm_map_character[] = { ",",".","?","!","<","\n",
											":",";","~","/",">","\n",
										   "@","#","$","%","=","\n",
										   "*","(",")","-","Bak",
										   ""

};

char * btnm_control[] = { "del","Up","Down","Num","Bak","FU" };
if (event == LV_EVENT_VALUE_CHANGED) {
	const char * txt = lv_btnm_get_active_btn_text(obj);
	if (txt == btnm_control[0]) { //del
		lv_ta_del_char(ta1);
	}
	else if (txt == btnm_control[1]) { //Up
		lv_btnm_set_map(obj, btnm_map_caps);//btnm_map_caps
		lv_btnm_set_btn_ctrl_all(obj, LV_BTNM_CTRL_CLICK_TRIG);
		check_threshold = true;
	}
	else if (txt == btnm_control[2]) { //Down
		lv_btnm_set_map(obj, btnm_map_lower);
		lv_btnm_set_btn_ctrl_all(obj, LV_BTNM_CTRL_CLICK_TRIG);
		check_threshold = true;
	}
	else if (txt == btnm_control[3]) { //Num
		lv_btnm_set_map(obj, btnm_map_nums);
		lv_btnm_set_btn_ctrl_all(obj, LV_BTNM_CTRL_CLICK_TRIG);
		check_threshold = true;
	}
	else if (txt == btnm_control[4]) { //return
		lv_btnm_set_map(obj, btnm_map_lower);
		lv_btnm_set_btn_ctrl_all(obj, LV_BTNM_CTRL_CLICK_TRIG);
		check_threshold = true;
	}
	else if (txt == btnm_control[5]) {
		lv_btnm_set_map(obj, btnm_map_character);
		lv_btnm_set_btn_ctrl_all(obj, LV_BTNM_CTRL_CLICK_TRIG);
		check_threshold = true;
	}
	else {
		lv_ta_add_text(ta1, txt);
	}
}

}

Plus: at the begainnng of btnm was created, add" lv_btnm_set_btn_ctrl_all(obj_kb, LV_BTNM_CTRL_CLICK_TRIG);", that fiist auto turn from “Caps_map” to “Lower_maps” as I described above disapears, and that phenomenon of firstly “Num” and “FU” btn presssed cause crash also fixed up. Amazing experience, so seems matters with “event”.

Form the code it seems you are using v6. Can you try it with v7 (latest master branch)

Note that, “btnm” was renamed to “btnmatrix”.

Today tried again with both V7 and V6, now I found the problem, seems I missed the “btn control state”,for each different btnm should set a different control map,like below:


All works as my expection.