Bart | 2 Jul 2009 15:14
Picon

pointer reference stays empty

Hi all,

--
System specs: Ubuntu Jaunty Jackelope 9.04 (Linux 2.6.28-13-generic), SDCC 2.9.0 #5416
Target processor: ADuC832 8051 compatible
--

Problem:
I have a pointer to an unsigned char, i put a char into the variable the pointer is pointing to, push it to some outputs and nothing happens....

Example code:

...
unsigned char * stream;
stream = (unsigned char *) malloc(1);
if(stream == NULL)
     return NULL;
*stream = (unsigned char) getchar(); // getchar returns just a char
P2 = *stream;
...

Nothing apears on the output port P2...
It has something to do with the pointer thats for sure, the assembly code is correct and if i replace the getchar function by a value it doesnt work either...
It looks like i just cant write a value to the variable the pointer is pointing to.

Now the following for example works:

unsigned char stream = 0xaa; // just an example value
P2 = stream;

Any thoughts?

Cheers

Bart

------------------------------------------------------------------------------
_______________________________________________
Sdcc-user mailing list
Sdcc-user@...
https://lists.sourceforge.net/lists/listinfo/sdcc-user
Li Xiaojun | 3 Jul 2009 05:10
Picon

[function pointer bug]The function pointer in struct located in code segment cannot work.

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);
}
------------------------------------------------------------------------------
Bodo Wenzel | 3 Jul 2009 08:25
Picon

Re: pointer reference stays empty

> if(stream == NULL)
>      return NULL;
Are you sure that malloc() returned a valid pointer?

For debugging I would change this code into:

if (stream == NULL) {
  P2 = 0xAA;
  return NULL;
}

Or, as I know assembler, I would look into the machine code to check it does 
The Right Thing(TM).

HTH, Bodo

------------------------------------------------------------------------------
Bart | 3 Jul 2009 09:48
Picon

Re: pointer reference stays empty

Yes the malloc is ok.
NULL is defined as (void *) 0 and that's not the content of stream, i did your test and he didn't put 0xaa on the output.

For example:

if(stream == NULL)
{
     P2 = 0xaa;
}
else
{
     P2 = 0xf0;
}

gives 0xf0 on the output

Even the simplest main with malloc fails:

void main(void)
{
     unsigned char * stream;
     stream = (unsigned char *) malloc(1);
     if(stream == NULL)
     {
          P2 = 0xf0;
     }
     else
     {
          *stream = 0xaa;
          P2 = *stream;
     }
}

Gives nothing on the output port P2

I also took a look at the assembly file and it looks fine to me for all my test programs.
I see that he loads 1 in the dptr, probably the 1 byte i want to allocate with malloc, then he lcall's the subroutine _malloc, then he moves the 3 byte address in r2, r3, r4. then the NULL check is nothing more than 3 times a compare and jump not equal on 0 value followed by placing 0xf0 on P2 like it should be.
In the other case i see that the pointer address is loaded, followed by putting 0xaa in the accumulator followed by an lcall to __gptrput like it should be.
Then the pointer address is moved again in the registers followed by a lcall to __gptrget and a move of the accumulator to P2 since __gptrget stocks his result in the accumulator.

;    main.c:12: test = (unsigned char *) malloc(1);
    mov    dptr,#0x0001
    lcall    _malloc
    mov    r2,dpl
    mov    r3,dph
    mov    r4,#0x00
;    main.c:13: if(test == NULL)
    cjne    r2,#0x00,00102$
    cjne    r3,#0x00,00102$
    cjne    r4,#0x00,00102$
;    main.c:15: P2 = 0xf0;
    mov    _P2,#0xF0
    sjmp    00105$
00102$:
;    main.c:19: *test = 0xaa;
    mov    dpl,r2
    mov    dph,r3
    mov    b,r4
    mov    a,#0xAA
    lcall    __gptrput
;    main.c:20: P2 = *test;
    mov    dpl,r2
    mov    dph,r3
    mov    b,r4
    lcall    __gptrget
    mov    _P2,a

It makes no sense to me, the only thing i can think of is that the compiler doesnt make the right hex file for loading in my µc...
Still thanks for the reply.

2009/7/3 Bodo Wenzel <bodowenzel-S0/GAf8tV78@public.gmane.org>
> if(stream == NULL)
>      return NULL;
Are you sure that malloc() returned a valid pointer?

For debugging I would change this code into:

if (stream == NULL) {
 P2 = 0xAA;
 return NULL;
}

Or, as I know assembler, I would look into the machine code to check it does
The Right Thing(TM).

HTH, Bodo


------------------------------------------------------------------------------
_______________________________________________
Sdcc-user mailing list
Sdcc-user-5NWGOfrQmnetEtDZOKyKiw@public.gmane.orgrge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

------------------------------------------------------------------------------
_______________________________________________
Sdcc-user mailing list
Sdcc-user@...
https://lists.sourceforge.net/lists/listinfo/sdcc-user
Bodo Wenzel | 4 Jul 2009 14:49
Picon

Re: pointer reference stays empty

Hi Bart,

Your analysis is well done, and I appreciate your assembler knowledge.

However, I'm not sure that I do understand what you mean by "Gives nothing on 
the output port P2." For the moment I assume that each line of P2 doesn't 
change its level, i.e. it stays at "1" which is the default after a reset. So 
it's possible that P2 is written with 0xFF.

BTW, you can check such a write with a pulldown resistor that lowers the 
voltage at a pin down to 3/4 or 1/2 of VCC. An oscilloscope will show the 
write access with a small impulse to VCC because the 8051 ports will reduce 
the builtin pullup value for two clock cycles.

My suggestion for the next steps would be:

If you can't use a simulator with the hex file, and if the only watchable 
output is P2,

1. Run three tests, each setting P2 with one byte of the generic pointer.

2. Check that the external (or internal?) memory at that address is working or 
at least should be by the schematics.

3. Invert the value before assigning it to P2, like "P2 = ~*stream;" I'd 
expect then every bit at "0".

If you have a simulator at hand, run the program with it. Well, you will have 
to step through the builtins, but perhaps the simulator can run a subroutine 
as one step.

Another issue is the malloc stuff. I'm not using SDCC currently and so I don't 
know how it works here. But I played a bit with z88dk, and there I had to set 
up malloc with some special functions and variables to get it working.

To say it shortly, these are the two most probable reasons:

- The memory pointed to by the return value of malloc() can't store anything 
because of a hardware problem. So a read from it returns 0xff which can be 
the value of an open databus.

- malloc() returns an arbitrary but reproducable pointer because the 
allocation management is not initialized. And the memory pointed to can't 
store any value and always returns 0xFF.

Bodo

------------------------------------------------------------------------------
Maarten Brock | 6 Jul 2009 15:21
Picon

Re: [function pointer bug]The function pointer in struct located in code segment cannot work.

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
> Sdcc-user@...
> https://lists.sourceforge.net/lists/listinfo/sdcc-user
>
>

------------------------------------------------------------------------------
Maarten Brock | 6 Jul 2009 15:10
Picon

Re: pointer reference stays empty

Hello Bart,

I agree with Bodo. Xdata is probably not set up correctly. Does your mcu
have internal xdata? And do you need to enable it? Otherwise I expect your
real external ram not to be working.

You should not need to initialize malloc, it's probably ok.

Greets,
Maarten

> Hi Bart,
>
> Your analysis is well done, and I appreciate your assembler knowledge.
>
> However, I'm not sure that I do understand what you mean by "Gives nothing
> on the output port P2." For the moment I assume that each line of P2
> doesn't change its level, i.e. it stays at "1" which is the default after
> a reset. So it's possible that P2 is written with 0xFF.
>
> BTW, you can check such a write with a pulldown resistor that lowers the
> voltage at a pin down to 3/4 or 1/2 of VCC. An oscilloscope will show the
> write access with a small impulse to VCC because the 8051 ports will
> reduce the builtin pullup value for two clock cycles.
>
> My suggestion for the next steps would be:
>
> If you can't use a simulator with the hex file, and if the only watchable
> output is P2,
>
> 1. Run three tests, each setting P2 with one byte of the generic pointer.
>
> 2. Check that the external (or internal?) memory at that address is
> working or at least should be by the schematics.
>
> 3. Invert the value before assigning it to P2, like "P2 = ~*stream;" I'd
> expect then every bit at "0".
>
> If you have a simulator at hand, run the program with it. Well, you will
> have to step through the builtins, but perhaps the simulator can run a
> subroutine as one step.
>
> Another issue is the malloc stuff. I'm not using SDCC currently and so I
> don't know how it works here. But I played a bit with z88dk, and there I
> had to set up malloc with some special functions and variables to get it
> working.
>
> To say it shortly, these are the two most probable reasons:
>
> - The memory pointed to by the return value of malloc() can't store
> anything
> because of a hardware problem. So a read from it returns 0xff which can be
> the value of an open databus.
>
> - malloc() returns an arbitrary but reproducable pointer because the
> allocation management is not initialized. And the memory pointed to can't
> store any value and always returns 0xFF.
>
> Bodo

------------------------------------------------------------------------------
Alistair Buxton | 7 Jul 2009 16:04
Picon

Z80 and custom crt0 - gsinit is pointing to GSFINAL instead of GSINIT

Hi,

When I use my custom crt0, in the final binary, gsinit: is pointing to
GSFINAL instead of GSINIT. Therefore, global variables do not get
initialised. Also, GSINIT is placed into DATA which seems to be wrong.
Finally, since my device only has RAM and not ROM, I don't think I
need separate CODE and DATA areas - all variables can be stored in
CODE like consts are. Is there some way to tell the compiler to do
that?

Here is my custom crt0:

;; crt0 for Actions chips.
;; Based on SDCC's z80 crt0
;; Modified by Alistair Buxton <a.j.buxton@...>

;; Generic crt0.s for a Z80
.module crt0
.globl _main

.area _HEADER (ABS)
;; Reset vector
.org 0
jp init

;; Vector used by firmware reloader
.org    0x10
di
xor a
out (0x4e), a
ld hl,#0x4000
ld de,#0x0000
ld bc,#0x4000
ldir
jp init

;; --------------------------------------------------
;; INT Vector 0x38
;; --------------------------------------------------
.org 0x38
jp int_ret
int_ret:
reti
;; --------------------------------------------------
;; NMI Vector 0x66
;; --------------------------------------------------
.org 0x66
jp nmi_ret
nmi_ret:
retn

.org 0x100 ; normal org
;.org 0xC00 ; leave room to copy in ADFU mode
init:
di ; disable interrupts
ld a, #0 ; and watchdog
out (0x4e), a

;; Stack at the top of zram1.
ld sp,#0x3fff

;; Initialise global variables
call    gsinit

call _main

jp _exit

;; Ordering of segments for the linker.
.area _HOME
.area _CODE
.area   _GSINIT
.area   _GSFINAL

.area _DATA
.area   _BSS
.area   _HEAP

.area   _CODE

__clock::
ld a,#2
rst     0x08
ret

_exit::
;; Exit - special code to the emulator
ld a,#0
rst     0x08
1$:
halt
jr 1$
nop

.area   _GSINIT
gsinit::

.area   _GSFINAL
ret

Here is the resulting .map:

Hexadecimal

Area                               Addr   Size   Decimal Bytes (Attributes)
--------------------------------   ----   ----   ------- ----- ------------
.  .ABS.                           0000   0000 =      0. bytes (ABS,CON)

     Value  Global
  --------  --------------------------------
    0000    l__BSS
    0000    l__CABS
    0000    l__HEAP
    0000    l__HOME
    0000    l__OVERLAY
    0000    s__HEADER
    0001    l__GSFINAL
    0013    l__DATA
    0060    l__GSINIT
    0111    l__HEADER
    0200    s__CODE
    0D52    l__CODE
    3100    s__DATA
    3113    s__GSINIT
    3113    s__HOME
    3113    s__OVERLAY
    3173    s__GSFINAL
    3174    s__BSS
    3174    s__CABS
    3174    s__HEAP

Hexadecimal

Area                               Addr   Size   Decimal Bytes (Attributes)
--------------------------------   ----   ----   ------- ----- ------------
_CODE                              0200   0D52 =   3410. bytes (REL,CON)

     Value  Global
  --------  --------------------------------
    0200    _int_handler
    0200    _int_handler_start
    0245    _int_handler_end
    0245    _main
    0245    _main_start
    02D2    _main_end
    02DD    _lcd_draw_mode
    02DD    _lcd_draw_mode_start
    02E9    _lcd_draw_mode_end
    0529    _lcd_command_mode
    0529    _lcd_command_mode_start
    0538    _lcd_command
    0538    _lcd_command_mode_end
    0538    _lcd_command_start
    0550    _lcd_command_end
    0550    _lcd_set_page
    0550    _lcd_set_page_start
    056C    _lcd_set_col
    056C    _lcd_set_col_start
    056C    _lcd_set_page_end
    059C    _lcd_draw
    059C    _lcd_draw_start
    059C    _lcd_set_col_end
    05B4    _lcd_cls
    05B4    _lcd_cls_start
    05B4    _lcd_draw_end
    05EA    _lcd_cls_end
    05EA    _lcd_test_char
    05EA    _lcd_test_char_start
    0673    _lcd_test_char_end
    0673    _lcd_write_string
    0673    _lcd_write_string_start
    0743    _lcd_write_char
    0743    _lcd_write_char_start
    0743    _lcd_write_string_end
    07EF    _lcd_write_char_end
    07EF    _lcd_write_hex
    07EF    _lcd_write_hex_start
    081A    _lcd_write_byte
    081A    _lcd_write_byte_start
    081A    _lcd_write_hex_end
    0845    _delay
    0845    _delay_start
    0845    _lcd_write_byte_end
    0886    _delay_end
    08C0    _usb_reset
    08C0    _usb_reset_start
    0921    _usb_check_length
    0921    _usb_check_length_start
    0921    _usb_reset_end
    0955    _usb_check_length_end
    0955    _usb_wait_ep_br
    0955    _usb_wait_ep_br_start
    0991    _usb_setup_epi
    0991    _usb_setup_epi_start
    0991    _usb_wait_ep_br_end
    09CB    _usb_read
    09CB    _usb_read_start
    09CB    _usb_setup_epi_end
    0A05    _usb_read_end
    0A05    _usb_write
    0A05    _usb_write_start
    0A5D    _usb_reenumerate
    0A5D    _usb_reenumerate_start
    0A5D    _usb_write_end
    0A6E    _usb_reenumerate_end
    0A6E    _usb_unsetup
    0A6E    _usb_unsetup_start
    0A85    _usb_setup
    0A85    _usb_setup_start
    0A85    _usb_unsetup_end
    0F47    __clock
    0F47    _usb_setup_end
    0F4B    _exit

Hexadecimal

Area                               Addr   Size   Decimal Bytes (Attributes)
--------------------------------   ----   ----   ------- ----- ------------
_DATA                              3100   0013 =     19. bytes (REL,CON)

     Value  Global
  --------  --------------------------------
    3107    _porttmp

Hexadecimal

Area                               Addr   Size   Decimal Bytes (Attributes)
--------------------------------   ----   ----   ------- ----- ------------
_GSINIT                            3113   0060 =     96. bytes (REL,CON)

     Value  Global
  --------  --------------------------------
    3173    gsinit

MODULES
FILE test.o
NAME test
FILE gfx.o
NAME gfx
FILE usb.o
NAME usb
FILE crt0.o
NAME crt0
USERBASEDEF
_CODE = 0x0200
_DATA = 0x3100

Thanks,

--
Alistair Buxton
a.j.buxton@...

------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have 
the opportunity to enter the BlackBerry Developer Challenge. See full prize 
details at: http://p.sf.net/sfu/blackberry
bobrob | 7 Jul 2009 21:48
Picon

Re: Z80 and custom crt0 - gsinit is pointing to GSFINAL instead of GSINIT


----- Alistair Buxton wrote:

> When I use my custom crt0, in the final binary, gsinit: is pointing to
> GSFINAL instead of GSINIT.

crt0 needs to be the first module in the list of modules you link.
If it is not first, then the gsinit label will not be ahead of the stuff
the compiler puts in the GSINIT area.  This is not documented
very well.  I think that when you let sdcc magically add crt0, it
places it ahead of everything else you link.  But when you use
the "--no-std-crto", it is up to you to put it first.

> Therefore, global variables do not get
> initialised. Also, GSINIT is placed into DATA which seems to be wrong.

This is also a symptom of crt0 not being linked first.  I think
the linker puts the areas in the order it first encounters them.
That is why all the areas are mentioned in the default crt0.s,
even if crt0 does not put anything in that area. 

> Finally, since my device only has RAM and not ROM, I don't think I
> need separate CODE and DATA areas - all variables can be stored in
> CODE like consts are. Is there some way to tell the compiler to do
> that?

I think if you omit the "--data-loc" from the linker options it
will put your data area right after the code.

Randy



.j.buxton-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>.j.buxton-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have 
the opportunity to enter the BlackBerry Developer Challenge. See full prize 
details at: http://p.sf.net/sfu/blackberry
_______________________________________________
Sdcc-user mailing list
Sdcc-user@...
https://lists.sourceforge.net/lists/listinfo/sdcc-user
Alistair Buxton | 7 Jul 2009 22:07
Picon

Re: Z80 and custom crt0 - gsinit is pointing to GSFINAL instead of GSINIT

2009/7/7  <bobrob@...>:
>
> ----- Alistair Buxton wrote:
>
>> When I use my custom crt0, in the final binary, gsinit: is pointing to
>> GSFINAL instead of GSINIT.
>
> crt0 needs to be the first module in the list of modules you link.
> If it is not first, then the gsinit label will not be ahead of the stuff
> the compiler puts in the GSINIT area.  This is not documented
> very well.  I think that when you let sdcc magically add crt0, it
> places it ahead of everything else you link.  But when you use
> the "--no-std-crto", it is up to you to put it first.

If I place crt0 first in the list of files for the linker, it produces
no output at all. No error messages, and no IHX file.
The linker seems to want the .o file with main() first.

>> Therefore, global variables do not get
>> initialised. Also, GSINIT is placed into DATA which seems to be wrong.
>
> This is also a symptom of crt0 not being linked first.  I think
> the linker puts the areas in the order it first encounters them.
> That is why all the areas are mentioned in the default crt0.s,
> even if crt0 does not put anything in that area.

Ok, but see above.

>> Finally, since my device only has RAM and not ROM, I don't think I
>> need separate CODE and DATA areas - all variables can be stored in
>> CODE like consts are. Is there some way to tell the compiler to do
>> that?
>
> I think if you omit the "--data-loc" from the linker options it
> will put your data area right after the code.

I don't want to move the data area, I want to get rid of the GSINIT
section and variable initialization code, and have the variables
initialized directly in code eg ".db <value>" - that is, I want the
compiler behaviour used for allocating consts to apply to all
variables. Since all memory is writable, having a separate piece of
code to initialize variables is a waste of space.

--

-- 
Alistair Buxton
a.j.buxton@...

------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have 
the opportunity to enter the BlackBerry Developer Challenge. See full prize 
details at: http://p.sf.net/sfu/blackberry

Gmane