From: Maarten B. <sou...@ds...> - 2009-07-06 13:50:17
|
Hi, It looks like you think you've found a bug. Posting it in the user mailing list might get you a quick answer. But if not, it is bound to be forgotten. Bugs should be reported in the bug tracker system. Please repost. Maarten > Hi all, > > We use SDCC with our project and we encountered some problems with the > function pointer in struct which located in code segment. > > The pointers point to the wrong address and sometimes the mcu resets or > cannot go on normally. > > This is the test sample below, we test the function with/without > parameters, > return values and called with/without asterisk, all of them cannot work. > > Because of this problem, we had to put the struct in the data ram and > waste > lots of data ram, this is a very bad choice to a limited resource device. > > can anyone tell me why this happend, is it a bug of sdcc? > > 1. CODE SAMPLE1: we want to use code segment structure to hold function > pointers. > This can not work > > #define NR_TEST_FUNCS 2 > struct test_funcs { > void (*non_one)(void); > void (*non_two)(void); > uint8_t (*ret_one)(void); > uint8_t (*ret_two)(void); > uint8_t (*par_one)(uint8_t p1); > uint8_t (*par_two)(uint8_t p1, uint8_t p2); > }; > > struct test_funcs *test_funcs[NR_TEST_FUNCS]; > uint8_t nr_test_funcs = 0; > > void register_test_func(struct test_funcs *funcs) > { > if (nr_test_funcs < NR_TEST_FUNCS-1) { > test_funcs[nr_test_funcs] = funcs; > nr_test_funcs++; > } > } > > void test_non_one(void) > { > dbg_dump(1); > } > > void test_non_two(void) > { > dbg_dump(2); > } > > uint8_t test_ret_one(void) > { > return 3; > } > > uint8_t test_ret_two(void) > { > return 4; > } > > uint8_t test_par_one(uint8_t p1) > { > return p1; > } > > uint8_t test_par_two(uint8_t p1, uint8_t p2) > { > return p1+p2; > } > > code struct test_funcs funcs1 = { > test_non_one, > test_non_two, > test_ret_one, > test_ret_two, > test_par_one, > test_par_two, > }; > > code struct test_funcs funcs2 = { > test_non_one, > test_non_two, > test_ret_one, > test_ret_two, > test_par_one, > test_par_two, > }; > > static void test_funcs_ptr(void) > { > uint8_t i; > register_test_func(&funcs1); > register_test_func(&funcs2); > > for (i = 0; i < nr_test_funcs; i++) { > (test_funcs[i]->non_one)(); > (test_funcs[i]->non_two)(); > (*(test_funcs[i]->non_one))(); > (*(test_funcs[i]->non_two))(); > dbg_dump((*(test_funcs[i]->ret_one))()); > dbg_dump((*(test_funcs[i]->ret_two))()); > dbg_dump((*(test_funcs[i]->par_one))(5)); > dbg_dump((*(test_funcs[i]->par_two))(5, 1)); > } > } > > void main(void) > { > main_debug(MAIN_DEBUG_INIT, 0); > system_init(); > test_funcs_ptr(); > main_debug(MAIN_DEBUG_INIT, 1); > > while (1); > } > > 2. We has to pass function pointers and save them in the memory > This can work. > > typedef uint8_t usb_cid_t; > typedef uint8_t usb_iid_t; > typedef uint8_t usb_eid_t; > typedef uint8_t usb_addr_t; > typedef uint16_t usb_tsize_t; > typedef uint8_t usb_esize_t; > > typedef void (*usb_io_cb)(void); > typedef usb_tsize_t (*usb_size_cb)(void); > > typedef uint8_t hid_rid_t; > typedef void (*hid_poll_cb)(uint8_t endp); > > struct hid_report { > uint8_t duration; > usb_tsize_t input_len; > usb_tsize_t output_len; > usb_io_cb input_data; > usb_io_cb output_data; > hid_poll_cb poll_intr; > usb_size_cb config_len; > usb_io_cb ctrl_data; > }; > > > hid_rid_t hid_register_report(uint8_t duration, > usb_tsize_t input_len, > usb_tsize_t output_len, > usb_io_cb input_data, > usb_io_cb output_data, > hid_poll_cb poll_intr, > usb_size_cb config_len, > usb_io_cb ctrl_data) > { > hid_rid_t rid = hid_nr_reports; > if (rid < NR_HID_REPORTS) { > hid_reports[rid].input_data = input_data; > hid_reports[rid].poll_intr = poll_intr; > hid_reports[rid].output_data = output_data; > hid_reports[rid].ctrl_data = ctrl_data; > hid_reports[rid].config_len = config_len; > hid_reports[rid].duration = duration; > hid_reports[rid].input_len = input_len; > hid_reports[rid].output_len = output_len; > > hid_rept_ctrls[rid].interval = 0; > hid_rept_ctrls[rid].flags = 0; > hid_nr_reports++; > } > return rid; > } > > void kbd_hid_init(void) > { > kbd_hid_rid = hid_register_report(HID_DURATION_NEVER, > KBD_HID_INPUT_BYTES, > KBD_HID_OUTPUT_BYTES, > kbd_input_data, > kbd_output_data, > kbd_poll_intr, > kbd_config_len, > kbd_ctrl_data); > kbd_capture_old = kbd_set_capture(kbd_handle_key_event); > } > ------------------------------------------------------------------------------ > _______________________________________________ > Sdcc-user mailing list > Sdc...@li... > https://lists.sourceforge.net/lists/listinfo/sdcc-user > > |