Setting CPUCR and Near Addressing Mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Setting CPUCR and Near Addressing Mode

2,184 Views
Helmut
Contributor II
Hello,
currently I'm working to become familiar with the CodeWarrior 6.2 C-compiler and linker for the ColdFire V1 (what I got with the BadgeBoard). There arose some questions... Can please anybody help?

I want to set the CPUCR register and used the instruction "movec d0,CPUCR" ("movec d0,0x802" ended up in an "illegal addressing mode" and an "illegal use of asm inline function" error message).
This instruction "movec d0,CPUCR" is displayed in the simulator assembly window as "DC.W 0x4E7B; Invalid opcode" and causes in an illegal instruction interrupt.
What went wrong? I could not find out how to write the CPUCR register. How can I write new contents into the CPUCR register?

Near data addressing mode:
CF-V1's RAM is small enough such that it could be addresed entirely in near addresing mode an I want to take advantage of this. Therefore I chose in the project settings / ColdFire Processor / Data Model the selection "Near (16 bit)". But all standard accesses (data not explicitely declared as "near") are still accessed in far mode.

I tried to understand the role of A5, the base address register for near accesses.
Its value, the address _SDA_BASE, seems quite arbitrary, just behind the sections with the data to be predefined (are these data not near addressable?) if you look at a sample or default linker control script. Additionally _SDA_BASE is defined *before* alignment to a long word boundary.
All this made me think, the value of A5, the symbolic address _SDA_BASE, may in fact be defined arbitrarily, just in the RAM area and before the 'near' data. So I tried out to define _SDA_BASE to the beginning of the RAM, 0xFF8000; without any other change a variable attributed 'near' was appearingly addressed correctly.
The help texts do not contain anything about _SDA_BASE or a general hint how the compiler treats near addresses. Or have I overseen it?
Possibly, I guess, any short address is translated to (<variables address>-_SDA_BASE) by the compiler and the linker computes the correct address as long as _SDA_BASE has a compatible definition. If this is true it should be documented...
Is this correct? Can anybody confirm or reject this or give me hints where to find more information or even a tutorial?

I whish you all a happy new year!
Thank you in advance and kind regards,
Helmut
Labels (1)
0 Kudos
3 Replies

562 Views
Helmut
Contributor II
Hello kef,
thank you for the quick response. I din't expect to get any answer in 2008...

Sorry, I wasn't clear enough:
"movec d0,CPUCR" is part of asm void _startup(void) {...} which is shown in more detail below. The instruction is commented out as it never worked until now.

Yes, A5 is set to _SDA_BASE. Thank you for the tip with negative offsets, which allow also to near address data in the predefined short data.

But how are the short (A5-relative) addresses computed? It would of course be logical to compute them "near_address= address-_SDA_BASE". But it isn't mentioned anywhere in the documentation. As the program is translated and linked even when _SDA_BASE is not defined, this symbol cannot be the (only) used base. But when I define _SDA_BASE with different values, the near addresses change accordingly such that the effective addresses are correct. Examples:

Below you will find some lines of the source code with some dummy variable declarations and the linker control file. _SDA_BASE is defined one time to ff8000 (at the beginning of the first data segment) and the other time to ff801c, the beginning of .nzbss, a noninitialized data segment.

Code:
          _SDA_BASE:             ff8000    ff801c     relative addresses of savedSRS       1C         0relative addresses of dummy          18        -4
 
Both variables which were accessed by near addresses get the correct relative addresses. The only difference between the 2 codes is the declaration of _SDA_BASE in the linker control file.

What happens when I use another symbol? I replaced the name _SDA_BASE by SDA_BASE2 (experimental computer sciences... :smileyhappy:) and the realtive addresses were computed relative to ff8000.

This lets me assume that
- ff8000 (beginning of RAM) is used by default, but
- _SDA_BASE is used if it is defined.
This sounds simple, but I would really like to know if it is correct; I couldn't find it mentioned in any documentation.

Explicit near/far declarations are obviously ignored, for example the near word nw or components of the near byte array (code below) are accessed in far mode.
Even when addresses are correct, the values written into the simulated RAM by the simulator are simply wrong. But this will be an extra thread when I don't find out why.

Again, thank you!
Helmut


Code:
============================================================================Source file:At first some data declarations of different kinds: __declspec(nzbss) static byte savedSRS; /* not cleared during startup */// dummy variables to check addressing mode
static far long fl;static near word nw;static word dummy= 0x1667;static near byte nbarr[]= {1, 2, 3, 4, 5, 6, 7, 8, 9};static far word fwarr[]= {11, 22, 33, 44, 55};static far word fw= 0x1234;...asm void _startup(void) {   move.w    #0x2700,sr  lea       _SP_INIT,a7  movea.l   #0,a6  link      a6,#0  lea       _SDA_BASE,a5  // move.l #0xc0000000,d0  // movec  d0,CPUCR      was "movec d0,0x802"  both versions don't work  jmp       _hal_init}static void _hal_init(void) { asm (naked);   savedSRS= SRS; SRS=0;    /* translated to and executed as follows:    MOVE.B 0xFFFF9800,D0  yields D0=82 (correct)    MOVE.B D0,28(A5)      simulator stores 00 at FFFF801C (wrong)    CLR.B 0xFFFF9800      clears SRS   (correct)    */  ...  nw= 0xaffe;   // MOVE.W #-20482,D0   MOVW.W D0,FFFF8020           -->far
  dummy= 0;     // CLR.W 20(A5)   correct (near)
  nbarr[2]=254; // (MOVE.B #-2,D1 earlier)   MOVE.B D1,FFFF8002     -->far
  // the addresses are far, but correct. The values written into
  // the simulated memory are wrong: nw= 0xC000, nbarr[2]= 0x04 ...
...
}============================================================================Linker control file:# Linker script for ColdFire MCF51JM128 - BadgeBoardRC Transmitter# Version 1.00 MEMORY {    vectortable (RX)  : ORIGIN = 0x00000000, LENGTH = 0x000003FE    nonvolatile (R)   : ORIGIN = 0x000003FE, LENGTH = 0x00000012    code        (RX)  : ORIGIN = 0x00000410, LENGTH = 0x0001FBF0    userram     (RWX) : ORIGIN = 0xFFFF8000, LENGTH = 0x00004000}SECTIONS {   ___RAM_ADDRESS   = 0x00800000;   ___RAM_SIZE      = 0x00004000;   ___FLASH_ADDRESS = 0x00000000;   ___FLASH_SIZE    = 0x00020000;   ___heap_size     = 0x0400;   ___stack_size    = 0x0400;  .userram:   {} > userram  .code:      {} > code  .text:      {    OBJECT(__startup,startup.c)     *(.text) .=ALIGN (4);    *(.rodata) .=ALIGN (4);    __DATA_ROM=.;  } >> code  .data: AT(__DATA_ROM) {    .=ALIGN (4);     __SDA_BASE=.;     .=ALIGN(4);    __DATA_RAM=.;      *(.data) .=ALIGN (4);      *(.sdata) .=ALIGN (4);    __DATA_END=.;    .=ALIGN (4);#   __SDA_BASE=.;  } >> userram  .bss:{ # uninitialized data, shall be zeroed out in startup    .=ALIGN (4);      *(.nzbss) .=ALIGN (4);     __START_BSS=.;      *(.sbss) .=ALIGN (4);      *(.bss) .=ALIGN (4);    __END_BSS=.;    __BSS_SIZE=__END_BSS -__START_BSS;    . = ALIGN(4);  } >> userram  .custom: {    __SP_END           = .;    __SP_INIT          = __SP_END + ___stack_size;  .=ALIGN (4);  } >> userram}

 
0 Kudos

562 Views
kef
Specialist I
Hi Helmut
 
I believe movec d0,cpucr works. I once tried to check if disabled flash speculation (FSD=1) makes execution any slower or not. I don't remember figures, but I believe write to cpucr worked. What I see now is that CW simulator hates movec ??,cpucr . But simulator seems to understand movec ??,vbr . So maybe try it on real hardware.
 
 
Regarding _SDA_BASE. I think compiler uses short, A5 relative addressing for all variables in .sbss and .sdata sections. Then linker relocates all near accesses to be _SDA_BASE relative, and _SDA_BASE is defined in lkf file. It's bad no error is generated when _SDA_BASE is undefined in both startup and lkf files, but at least you should shot twice to your foot to make it not working :smileyhappy:. So for me everything looks right, or I don't see something.
 
You say explicit far/near are ignored. near keyword doesn't apply to short section addressing (sbss/sdata) using A5 relative addressing. Absolute 16-bit addressing range is from 0 to 7FFF, and from FFFF8000 to FFFFFFFF. QE (and probably all existing V1-ones) don't have RAM (and RW variables) in near addressing range. Only peripheral registers FFFF8000-FFFFFFFF, vectors (0..) and first 32k of flash 0-00007FFF.
 
These lines in CW6.2 should cause linker error, illegal 16-bit absolute address:
 
static near word nw; 
static near byte nbarr[]= {1, 2, 3, 4, 5, 6, 7, 8, 9};
 
To use short, A5 relative addressing, you should make sure Code Generation->Coldfire Processor-> "Use .sbss/.sdata for:" setting is set to All data or "All data smaller than" setting is set higher than 0.
 
 
0 Kudos

562 Views
kef
Specialist I
Regarding movec  to cpucr. Are you trying inline asm with "" like this
  asm{ "movec  d0,cpucr"}; ? Try without "
 
 asm{  movec  d0,cpucr};
 
Near accesses, relative to A5, seem to apply to .sbss and .sdata sections only. Try changing .sbss/.sdata setting to All data or incrementing All data smaller than setting.
 
_SDA_BASE is defined in linker file:
 
...
    *(.sdata)
    . = ALIGN (0x4);
    __END_SDATA = .;
    ___DATA_END = .;
    __SDA_BASE = .;
    . = ALIGN (0x4);
  } >> userram
  .bss :
  {
    ___BSS_START = .;
    __START_SBSS = .;
    *(.sbss)
    . = ALIGN (0x4);
...
 
_SDA_BASE points to the end of .sdata and to the start of .sbss . So that near, A5 relative access can cover be about 32kB of sbss (positive A5 offsets) and about 32kB of .sdata (negative A5 offsets). A5 is set to _SDA_BASE in startcf.c .
 
Kind Regards and Happy New Year!
0 Kudos