Author Topic: Accessing registers without pointers  (Read 9345 times)

Offline Richard

  • Newbie
  • *
  • Posts: 44
    • View Profile
Accessing registers without pointers
« on: October 26, 2007, 01:59:21 AM »
CONTEXT:
The Freescale Application Note AN2616, "Getting Started with HCS08 and CodeWarrior Using C", section 6.6, recommends defining a register via a structure, as in this example:
Code: [Select]
/*** DBGC - Debug Control Register ***/
typedef union {
  byte Byte;
  struct {
    byte RWBEN :1; /* Enable R/W for Comparator B */
    byte RWB :1; /* R/W Comparison Value for Comparator B */
    byte RWAEN :1; /* Enable R/W for Comparator A */
    byte RWA :1; /* R/W Comparison Value for Comparator A */
    byte BRKEN :1; /* Break Enable */
    byte TAG :1; /* Tag/Force Select */
    byte ARM :1; /* Arm Control */
    byte DBGEN :1; /* Debug Module Enable */
  } Bits;
} DBGCSTR;
extern volatile DBGCSTR _DBGC @0x00001816;
using these data types:
Code: [Select]
/* Types definition */
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
typedef unsigned long dlong[2];

To access the bits of DBGC, you can write things like
Code: [Select]
DBGC.Bits.RWB = 1; /*Set RWB bit of DBGC */
DBGC.Bits.RWB = 0; /*Clear RWB bit of DBGC */
Note that this avoids the use of a pointer to access DBGC by telling the compiler where it is located.

PROBLEM:
This may work fine for the CodeWarrior HCS08 compiler but not for either the CodeWarrior Coldfire or the Microsoft Visual Studio 2005 compiler.  Both are unhappy about dealing with a statement like
  extern volatile DBGCSTR _DBGC @0x00001816;
which is supposed to declare that DBGC is at location 0x00001816.

QUESTION:
How can I achieve the same effect with the CodeWarrior and the Microsoft Visual Studio compilers?  I.e., how can I tell these compilers what address to assign to a variable?

Thanks,
    Richard

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Accessing registers without pointers
« Reply #1 on: October 26, 2007, 12:10:20 PM »
Hi Richard

I think that the following solution may be appropriate:

#if defined _WINDOWS
    DBGCSTR test_structure = {0};
    extern volatile DBGCSTR *_DBGC = (volatile DBGCSTR *)&test_structure;
#elif defined _CODEWARRIOR
    extern volatile DBGCSTR *_DBGC = (volatile DBGCSTR *)0x00001816;
#else
    extern volatile DBGCSTR _DBGC @0x00001816;
#endif


Codewarrior will (presumably) not understand that @ means a pointer address so the above defines _DBGC it so that it does.
In the case of VS the same solution is valid, but the address 0x00001816 will cause any accesses to exception. Therefore I have added a test structure which allows the bits to really be set in a structure in memory. Since the Windows PC will not actually have the registers, this is a method of 'simulating' at least the behaviour of access to the registers to check that they are doing what is expected before testing on a target. I am assuming that the CW target has access to the registers (which possibly also requires different physical addresses to 0x00001816 to be set).

As I quick test, I compiled the following code in VS and it successfully modifies the bits in the test structure when the test function is called.

Note that your example code was not using the pointer to manipulate the bits but doing it directly in the struct. Thererfore I have two structs - one local and one over a pointer (difference is the . and -> accesses) to illustrate both methods.


Code: [Select]
/* Types definition */
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
typedef unsigned long dlong[2];


/*** DBGC - Debug Control Register ***/
typedef union {
  byte Byte;
  struct {
    byte RWBEN :1; /* Enable R/W for Comparator B */
    byte RWB :1; /* R/W Comparison Value for Comparator B */
    byte RWAEN :1; /* Enable R/W for Comparator A */
    byte RWA :1; /* R/W Comparison Value for Comparator A */
    byte BRKEN :1; /* Break Enable */
    byte TAG :1; /* Tag/Force Select */
    byte ARM :1; /* Arm Control */
    byte DBGEN :1; /* Debug Module Enable */
  } Bits;
} DBGCSTR;

DBGCSTR DBGC;

#if defined _WINDOWS
    DBGCSTR test_structure = {0};
    extern volatile DBGCSTR *_DBGC = (volatile DBGCSTR *)&test_structure;
#elif defined _CODEWARRIOR
    extern volatile DBGCSTR *_DBGC = (volatile DBGCSTR *)0x00001816;
#else
    extern volatile DBGCSTR _DBGC @0x00001816;
#endif


static void test(void)
{
DBGC.Bits.RWB = 1; /*Set RWB bit of DBGC */
DBGC.Bits.RWB = 0; /*Clear RWB bit of DBGC */

_DBGC->Bits.RWB = 1;
_DBGC->Bits.RWBEN = 1;
}

Regards

Mark


Note: I realised that you originally wrote that the recommended method avoids the use of pointers.
In this case I can't think of an equivalent method to make the compiler work directly with a structure at a fixed address. I wonder whether someone else knows of a trick?

« Last Edit: October 26, 2007, 08:52:33 PM by mark »