Menu

#562 xdata initialization fails on Cygnal parts

closed-fixed
7
2013-05-25
2003-08-09
Anonymous
No

SDCC puts in code for initializing xdata that directly
writes to port 2. The xdata command in Cygnal's 8051's
accesses interal "extern data"--it is not external. As a
result, the direct control of P2 to set the proper page
before doing the movx @r0, a command fails on these
products.

robertr@hildalecity.com

Discussion

  • Frieder Ferlemann

    Logged In: YES
    user_id=589052

    Hi,

    you're probably talking about code that is generated by

    _mcs51_genXINIT in sdcc/src/mcs51/main.c near line 172

    you can adapt the code there (hopefully 'just' use another
    paging
    register?), then recompile sdcc and have a go at your code
    again.

    Could you give a pointer as to which/how the cygnal
    devices differ?

    Frieder

     
  • Nobody/Anonymous

    Logged In: NO

    I am using W95 (not linux) but have MSVC 6 for programming
    C++. I bought it but never got good at it; is SDCC adaptable
    to MSVC 6 for a WIN32 console application? The place you
    mentioned is the perfect place to put in my own initialization
    code that doesn't use P2. Maybe you can give a pointer or
    two on recompiling the source with MSVC Visual Studio.

    While we are recompiling the source, there is a pointer to
    function error that ought to be found where calling a function
    from an array of function pointers generates bad code
    because someone used the wrong addressing mode; this
    should be a very simple fix of the proper fprintf statement.

     
  • Jesus Calvino-Fraga

    Logged In: YES
    user_id=603650

    Check the sdcc manual, section 2.4.7: Building SDCC Using
    Microsoft Visual C++ 6.0/NET (MSVC) at

    http://sdcc.sourceforge.net/doc/sdccman.html/node14.html#S
    ECTION00034700000000000000

    Jesus

     
  • Frieder Ferlemann

    Logged In: YES
    user_id=589052

    Hi,
    with the cygnal deviating from the standard 8051 core
    patching the compiler currently seems the only way
    to properly initialize it. This is not nice.
    Maybe the 8051 port should switch to an initialization
    via an external file crt0.s as the z80 port does?

    Frieder

     
  • Frieder Ferlemann

    • priority: 5 --> 7
     
  • Jesus Calvino-Fraga

    Logged In: YES
    user_id=603650

    There is a simpler solution to this problem than using an
    external initialization file crt0.s: If option --no-xinit-opt is
    used, the initialiazion of external RAM can be placed directly
    in _sdcc_external_startup(). A bonus to this would be the
    use of dual dptr registers when available.

    Jesus

     
  • Nobody/Anonymous

    Logged In: NO

    I did as advised; used the --no-xinit-opt and source code
    something to this effect (actual tested source code not
    available at time of posting)

    main() {
    ... Variable declarations
    _asm
    mov r0, #l_XINIT
    mov r1, #(l_XINIT >> 8)
    mov r2, #s_XINIT
    mov r3, #(s_XINIT >> 8)
    mov r4, #s_XISEG
    mov r5, #(s_XISEG >> 8)
    00001$:
    mov a, #255
    add a, r0
    mov r0, a
    mov a, #255
    addc r1, a
    mov r1, a
    jnc 00002$
    mov dpl, r2
    mov dph, r3
    clr a
    movc a, @a+dptr
    inc dptr
    mov r2, dpl
    mov r3, dph
    mov dpl, r4
    mov dph, r5
    movx @dptr, a
    inc dptr
    mov r4, dpl
    mov r5, dph
    sjmp 00001$
    00002$:
    _endasm;

    I am wondering why not use something like what is shown
    above so 8051 variants that don't accept P2 paging for xdata
    will still work? This code is only executed once on startup, so
    efficiency and code size are not a primary concern; I would
    tend to side with greater reliability than code size or
    efficiency in this case. I am posting this mostly as a solution
    around this problem, since I consider the problem essentially
    solved, now.

    robertr@hildalecity.com

     
  • Paul Stoffregen

    Paul Stoffregen - 2003-08-30

    Logged In: YES
    user_id=104682

    Perhaps the "hard coded" initialization should be a simple
    LCALL instruction, and move this code into the library.
    This same approach is used for _sdcc_external_startup()
    today, and it allows a "default" version to be in the
    library, and users can easily code their own and the linker
    will use their code rather than the default copy in the
    standard library.

    -Paul

     
  • Van Mierlo Ingenieursbureau

    Logged In: YES
    user_id=591031

    Hello Frieder,

    Since nobody answers your question, I'll give you the answer.
    The cygnal devices come in four different flavours with regard
    to internal xram:

    1) no xram, nor external memory interface: nothing to be done

    with internal xram/external memory interface:
    2) 'just' another paging register EMI0CN at 0xAF
    3) 'just' another paging register EMI0CN at 0xAA
    4) not 'just' another paging register, but a paging register
    EMI0CN at 0xA2 in an sfr-page (0).

    Especially the last one will give most problems I guess. The
    best approach I see is either use the generic solution or use
    the move-it-to-library option. The last one would be my
    preferred option.

    greetings,
    Maarten Brock

     
  • Frieder Ferlemann

    Logged In: YES
    user_id=589052

    Hi,

    > The cygnal devices come in four different
    > flavours with regard to internal xram:
    > 1) no xram, nor external memory interface: nothing to be
    done
    > 2) 'just' another paging register EMI0CN at 0xAF
    > 3) 'just' another paging register EMI0CN at 0xAA

    These could maybe be resolved with the help of the linker.
    If SDCC would output "P2_ALIKE_PDATA_PAGING_SFR" instead
    of "P2", then the linker could first try to link to
    location "P2_ALIKE_PDATA_PAGING_SFR" (which would be
    EMI0CN
    on a cygnal and something else for f.e. a Triscend)
    and if this fails fall back to "P2".
    The long name is chosen here for clarity and not
    as a real proposal - Comments?

    > 4) not 'just' another paging register, but a paging
    register
    > EMI0CN at 0xA2 in an sfr-page (0).

    Funny that the paging register itself is a paged register
    =:O
    Probably it will stay the responsibility of
    the programmer to asure that EMI0CN is paged
    in when it is needed - if that is true then the
    above proposal should be OK.

    Please note: If you want to use generic pointers
    (on a cygnal) pointing to addresses in pdata
    then you won't like the use of "p2" in:
    sdcc/device/lib/_gptrget.c
    (f.e. memcpy and friends are calling gptrget)
    You probably have three options there:
    a) cast your pointer to (xdata char*),
    b) provide your own gptrget function
    c) persuade users/developers to have a slightly
    slower but cygnal compatible function;)

    Greetings,

    Frieder

     
  • Van Mierlo Ingenieursbureau

    Logged In: YES
    user_id=591031

    Hello,

    I've seen in the logs that the use of P2 in _gptrget.c is
    already disabled. Now I've looked in the source tree and found
    only two other places where it is used: in mcs51/main.c in the
    initialisation as already observed and I think this really should
    be moved to a library function. And the other place is in
    SDCCglue.c (line 1801) for setting up the xstack. I think this
    should be moved into _sdcc_external_startup() where it can
    be changed/overridden by the user.

    Btw, two questions: Is it ensured that the xstack area starts
    on a 256 byte aligned page? (And how?) And what happens if
    one compiles _sdcc_external_startup() with --xstack? I think
    this will go wrong and there should be a warning about it in
    _startup.c and the documentation.

    Greetings,
    Maarten

     
  • Erik Petrich

    Erik Petrich - 2004-03-18

    Logged In: YES
    user_id=635249

    With the changes noted in ChangeLog 1.683, initialization
    can now be easily compatible with Cygnal (Silicon Labs)
    parts. For most cases, just define the sfr _PAGESFR at the
    location of the EMI0CN register. For example, include the
    declaration:

    sfr at 0xaf _PAGESFR; /* EMI0CN at 0xAF */

    in any C file linked in a project.

    Most of the run-time startup/initialization is in a library
    now and thus can be overridden at the local level if more
    complex customizations are needed.

     
  • Erik Petrich

    Erik Petrich - 2004-03-18
    • labels: --> mcs51(8051) target
    • milestone: --> fixed
    • assigned_to: nobody --> epetrich
    • status: open --> closed-fixed
     
  • Maarten Brock

    Maarten Brock - 2004-03-18

    Logged In: YES
    user_id=888171

    Thanks Erik,

    I was recently looking into this issue as well, but wasn't sure
    how to implement the asm code into the libraries. Thanks for
    this fix.

    However, the sfr name you chose is not ideal for silabs
    processors. Some of them have so many sfr's that they don't
    fit in 128 positions. So they implemented sfr-paging with some
    common sfr's in all pages and others at overlapping addresses
    in different pages (EMI0CN is one of them). Now guess what,
    the name they use to select the sfr-page is SFRPAGE. May I
    suggest another name for _PAGESFR: _XPAGE.

    Furthermore, if I were to create an example crtxinit.asm and
    crtxstack.asm for one of those sfr-paging mcu's (F12x), could
    it be added to the examples? After I hear from you, I will also
    update the silabs header files.

    Greets,
    Maarten

     
  • Erik Petrich

    Erik Petrich - 2004-03-18

    Logged In: YES
    user_id=635249

    Ok, _PAGESFR is now _XPAGE. I had browsed a number of
    Silicon Lab's databooks looking for one that described the
    case in which EMI0CN itself was paged, but couldn't find it
    (they have so many databooks to cover their myriad of
    implementations!)

    An example of customizing crt*.asm would be great.

     
  • Maarten Brock

    Maarten Brock - 2004-03-18

    Logged In: YES
    user_id=888171

    Hi Erik,

    Looking into your code some more, I see you initialize
    __start__xstack in src/mcs51/main.c (181) to the start of
    xram. If however this is not on a page boundary, the
    allocation for it overflows the page. See src/SDCCglue.c
    (1760). Maybe it's wise to change this allocation to use only
    the rest of this page (256 - (options.xdata_loc % 256)).

    And why doesn't crtxinit.asm have some .globl entries? And
    while you're at it, untabify the file please.

    SDCC is getting better every day. Thanks.
    Maarten

     

Log in to post a comment.