Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

__at, reserving space, and initializers.

2014-03-15
2014-03-20
  • Robert Baruch
    Robert Baruch
    2014-03-15

    $ sdcc --version
    SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8 3.4.0/rc1/ #8960 (Mar 14 2014) (Mac OS X x86_64)

    So on a Z80, I'd like to reserve RAM 0x3C00-0x3FFF as video RAM, with allocatable code, data, and stack anywhere but there.

    The manual implies that this will not work:

    volatile __at (0x3C00) char videoRam[0x300];
    

    That will only say that videoRam = 0x3C00, but it will not reserve that space, and the compiler will still feel free to place whatever variables it wants in that space. The .asm file shows this:

    ;--------------------------------------------------------
    ; ram data
    ;--------------------------------------------------------
            .area _DATA
    _videoRam       =       0x3c00
    

    This, however, does work:

    volatile _at (0x3C00) char videoRam[0x300] = {0};
    

    While that does reserve space in the output, it also incurs a useless write:

    ;--------------------------------------------------------
    ; absolute external ram data
    ;--------------------------------------------------------
            .area _DABS (ABS)
            .org 0x3C00
    _videoRam::
            .ds 768
    ;--------------------------------------------------------
    ; global & static initialisations
    ;--------------------------------------------------------
            .area _HOME
            .area _GSINIT
            .area _GSFINAL
            .area _GSINIT
    ;test.c:1: volatile __at (0x3C00) char videoRam[0x300] = {0};
            ld      hl,#_videoRam+0
            ld      (hl),#0x00
    

    My questions are:

    1. Is there some other way to get videoRam declared as an uninitialized data space that the compiler will not treat as fair game for variable allocation?
    2. Is there a real example where it makes sense to declare an uninitialized volatile __at and letting the compiler allocate on top of it?

    Thanks!

     
  • Maarten Brock
    Maarten Brock
    2014-03-15

    This is for backward compatibility as it once only supported __at for uninitialized variables and could be used for overlaying.

    Another option you have is to place part of your code in a separate codeseg and locate that after the video ram.

     
  • Robert Baruch
    Robert Baruch
    2014-03-16

    OK, I've made a copy of crt0.s and changed the middle to this:

        ;; Ordering of segments for the linker.
        .area   _HOME
        .area   _CODE
    
        .area   _VRAM (ABS)
        .org    0x3C00
        .ds     768
    
        .area   _CODE1 (ABS)
            .org    0x4000
    
        .area   _INITIALIZER
        .area   _GSINIT
        .area   _GSFINAL
        .area   _DATA
        .area   _INITIALIZED
        .area   _BSEG
        .area   _BSS
        .area   _HEAP
    

    Is this a reasonable way to declare fixed areas of the address space?

    I compiled the modified crt0.s using sdasz80 -plogff, and wrote some quick test functions. I compiled the whole thing with the --no-std-crt0 option, It put the functions in the _CODE segment at 0x0200.

    Then, when I added #pragma codeseg _CODE1 to the file with the test functions and recompiled, it put the functions in the _CODE1 segment... except at 0x8000, not 0x4000 as expected.

    I'm just not sure how to do this. Any guidance would be appreciated!

    Area                                    Addr        Size        Decimal Bytes (Attributes)
    --------------------------------        ----        ----        ------- ----- ------------
    __CODE1                             00008010    0000000C =          12. bytes (REL,CON)
    
          Value  Global                              Global Defined In Module
          -----  --------------------------------   ------------------------
         00008010  _main                              test
         00008010  _main_start                        test
         00008016  _main_end                          test
         00008016  _silly                             test
         00008016  _silly_start                       test
         0000801C  _silly_end                         test
    
     
  • Robert Baruch
    Robert Baruch
    2014-03-16

    OK, I think I've solved this. I'd really like to put this in the documentation. Really, all the information is there, it's just pulling it together that was problematic.

    Attached is my modified crt0.s (I changed it from the original post so that _CODE1 is not (ABS), since we're specifying that on the command line.

    The test file (test.c):

    volatile __at (0x3C00) char videoRam[0x300];
    
    void main(void) {
        videoRam[0] = 'A';
    }
    
    void silly(void) {
        videoRam[0] = 'B';
    }
    

    Commands:

    $ sdasz80 -plogff crt0_trs80.s
    $ sdcc -mz80 --verbose -c test.c --codeseg CODE1
    $ sdcc -mz80 --verbose -Wl-b_CODE1=0x4000 --no-std-crt0 test.rel crt0_trs80.rel
    

    And... that works:

    Area                                    Addr        Size        Decimal Bytes (Attributes)
    --------------------------------        ----        ----        ------- ----- ------------
    _CODE1                              00004000    0000000C =          12. bytes (REL,CON)
    
          Value  Global                              Global Defined In Module
          -----  --------------------------------   ------------------------
         00004000  _main                              test
         00004000  _main_start                        test
         00004006  _main_end                          test
         00004006  _silly                             test
         00004006  _silly_start                       test
         0000400C  _silly_end                         test
    
     
    Attachments
  • Maarten Brock
    Maarten Brock
    2014-03-17

    Ah, this triggered another good option in my mind. You can create an asm file that allocates an absolute area without initializing it. In this case you don't need to change crt0.s and don't need a separate codeseg. Use an absolute segment (.area), locate it where you want (.org) and allocate space (.ds). The absolute segment will be linked first and the rest (_CODE) will be wrapped around it.

    ; vram.s
    
        .area   _VRAM (ABS)
        .org    0x3C00
        .ds     768
    

    Hope this helps,
    Maarten

     
  • Robert Baruch
    Robert Baruch
    2014-03-20

    Oh, that's good, I didn't know that _CODE would be wrapped around the area. Very cool, thanks!