Problems with Port definition...CAN Module...Cosmic Compiler

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

Problems with Port definition...CAN Module...Cosmic Compiler

3,661 Views
Piete
Contributor I
hello,

I just write a function for initialization of the CAN modules of a HCS12 using cosmic compiler version 4.4.6. Now I have the following problem. I pass the number of the CAN module which should be initialized to a function. The number of the CAN module is stored in the variable CANm;
I defined CAN0 in iosdp256.h:
Code:
#define CAN0 0x0140;
Then I defined the following in iosdp256.h:
Code:
#define CANCTL0   0X00   
#define CANCTL1   0X01                             
#define CANBTR0   0X02                          
#define CANBTR1   0X03                          
#define CANRFLG   0X04                          #define CANRIER   0X05           #define CANTFLG   0X06                          #define CANTIER   0X07        #define CANTBSEL  0X0A          
#define CANIDAC   0x0B         
#define CANIDAR0  0x10    #define CANIDAR1  0x11    #define CANIDAR2  0x12    #define CANIDAR3  0x13    #define CANIDMR0  0x14    #define CANIDMR1  0x15    #define CANIDMR2  0x16    #define CANIDMR3  0x17    #define CANIDAR4  0x18    #define CANIDAR5  0x19    #define CANIDAR6  0x1A    #define CANIDAR7  0x1B    #define CANIDMR4  0x1C    #define CANIDMR5  0x1D    #define CANIDMR6  0x1E    #define CANIDMR7  0x1F 

 I want to call a function like

Code:
CANInit(CAN0);

 To enable the CAN module CAN0 I wanted to use
Code:
_IO(CANm + CANCTL1) |= 0x80;

 because in iosdp256.h is defined

Code:
#ifndef _BASE#define _BASE 0#endif#define _IO(x) @(_BASE)+(x)

But I always get the error message "bad space modifier" and "invalid lvalue" for the lines with  _IO(.......)|=... .

Here once again more clear:
Code:
#include <iosdp256.h>                   /* contains register definitions */
                                        /* for the 9S12DP256             */
void CANInit(unsigend char CANm)
{
    _IO(CANModule + CANCTL0) |= 0x01;    // Enter Initialization-Mode
    _IO(CANm + CANCTL1) |= 0x80;         // Enable CAN module CAN0
}

CANInit(CAN0);


Could someone tell me what is wrong or how I can solve the problem?

Best regards
Labels (1)
0 Kudos
8 Replies

766 Views
kef
Specialist I
This is not C:
 
#define _IO(x) @(_BASE)+(x)
 
Try
 
#define _IO(x) (*(volatile char*)(_BASE + x))
0 Kudos

766 Views
Piete
Contributor I
Hello,

that

   #define _IO(x) (*(volatile char*)(_BASE + x))

 does not work.

If I use this I get a lot of errors in the iosdp256.h.

It is also defined.....
Code:
volatile __uchar CAN0CTL0     _IO(0x140);  /* CAN0 control register 0 */volatile __uchar CAN0CTL1     _IO(0x141);  /* CAN0 control register 1 */volatile __uchar CAN0BTR0     _IO(0x142);  /* CAN0 bus timing register 0 */
......
....
...
..
.
in the iosdp256.h.

If I use the following:
Code:
void CANInit(void){    CAN0CTL0 = 0x01;          // Enter Initialization Mode    CAN0CTL1 = 0x80;           // CANE = 1 THE MSCAN module is enabled}

CANInit();

it works, but then I can not pass the module I want to initialize. I have hard coded the module which should be initialize.
 


 

0 Kudos

766 Views
kef
Specialist I
Of course it won't work this way:
 
volatile __uchar CAN0CTL0     _IO(0x140);  /* CAN0 control register 0 */
 
 
But this should work
 
#define CAN0CTL0 _IO(0x140)
 
 
 
Not sure what you mean by "can't pass the module". Is it something like this:
 
 
#define CANCTL0(base) _IO(base+0)
#define CANCTL1(base) _IO(base+1)
...
 
#define CAN0 &CAN0CTL0
#define CAN1 &CAN1CTL0
#define CAN2 &CAN2CTL0
...
 
and then
 
   CANCTL1(CAN0) = 55;
   CANCTL1(CAN2) = 55;
 
?
0 Kudos

766 Views
Piete
Contributor I
Hello,

it is something like that:

          #define CANCTL0(base) _IO(base+0)
          #define CANCTL1(base) _IO(base+1)

Normally you use for example

          CAN0CTL0 = 0x01;              // Enter Initialization Mode

CAN module 0; control register 0;set bit 0 to 1 to enter initialization Mode
But if I use this I have to hard code the initialization of the CAN module.

In iosdp256.h it is defined:

Code:
#define _BASE    0
#endif#define _IO(x)    @(_BASE)+(x)volatile __uchar CAN0CTL0     _IO(0x140);  /* CAN0 control register 0 */

 
Now I want to write a function for all CAN modules so that I only have to call a function, e.g. CANInit and pass the number of the CAN module which should be initialized.

          e.g. CANInit(CAN0);

So I definded additionally:

Code:
#define CAN0      0x0140  // First address for MSCAN0  #define CANCTL0   0X00    // Control register 0

 Then I wanted to use it like that:

Code:
CANInit(CAN0);// CANInit(0x140};

CANInit(CANm)
{
    _IO(CANm+CANCTL0) |= 0x01; //_IO(0x140+0x00) |= 0x01;
}
 

That does not work.

I tried to use:
 
         
Code:
#define CANCTL0(base) _IO(0x00+base);   // in iosdp256.hCANInit(CAN0);   //CANInit(0x140);

CANInit(CANm){    CANCTL0(CANm) |= 0x01;    //CANCTL0(0x140);
}

But then I get the error "bad space modifier" in the line of "CANCTL0(CANm) |= 0x01;"

The error means:

"bad space modifier - a modifier beginning with a @ character is not
followed by an identifier"
 

If I use

          volatile __uchar CANCTL0(base) _IO(0x00+base);

instead of

          #define CANCTL0(base) _IO(0x00+base);


But then I get the error " base undefinded"



         
0 Kudos

766 Views
Lundin
Senior Contributor IV
Naturally you have to define "base" to the CAN0 offset.

Let me save you some headache and post my own code for this:

typedef volatile unsigned char* CAN_port;

#define CAN0 (&CAN0CTL0)
#define CAN1 (&CAN1CTL0)
#define CAN2 (&CAN2CTL0)
#define CAN3 (&CAN3CTL0)
#define CAN4 (&CAN4CTL0)

#define reg_CANCTL0(x)  (*((CAN_port)x + 0x00))   /* Control Register 0                      */
#define reg_CANCTL1(x)  (*((CAN_port)x + 0x01))   /* Control Register 1                      */
#define reg_CANBTR0(x)  (*((CAN_port)x + 0x02))   /* Bus Timing Register 0                   */
#define reg_CANBTR1(x)  (*((CAN_port)x + 0x03))   /* Bus Timing Register 1                   */
#define reg_CANRFLG(x)  (*((CAN_port)x + 0x04))   /* Receiver Flag Register                  */
#define reg_CANRIER(x)  (*((CAN_port)x + 0x05))   /* Receiver Interrupt Enable Register      */
#define reg_CANTFLG(x)  (*((CAN_port)x + 0x06))   /* Transmitter Flag Register               */
#define reg_CANTIER(x)  (*((CAN_port)x + 0x07))   /* Transmitter Interrupt Enable Register   */
#define reg_CANTARQ(x)  (*((CAN_port)x + 0x08))   /* Transmitter Message Abort Control       */
#define reg_CANTAAK(x)  (*((CAN_port)x + 0x09))   /* Transmitter Message Abort Control       */
#define reg_CANTBSEL(x) (*((CAN_port)x + 0x0A))   /* Transmit Buffer Selection               */
#define reg_CANIDAC(x)  (*((CAN_port)x + 0x0B))   /* Identifier Acceptance Control Register  */
#define reg_CANRXERR(x) (*((CAN_port)x + 0x0E))   /* Receive Error Counter Register          */
#define reg_CANTXERR(x) (*((CAN_port)x + 0x0F))   /* Transmit Error Counter Register         */
#define reg_CANIDAR0(x) (*((CAN_port)x + 0x10))   /* Identifier Acceptance Register 0        */
#define reg_CANIDAR1(x) (*((CAN_port)x + 0x11))   /* Identifier Acceptance Register 1        */
#define reg_CANIDAR2(x) (*((CAN_port)x + 0x12))   /* Identifier Acceptance Register 2        */
#define reg_CANIDAR3(x) (*((CAN_port)x + 0x13))   /* Identifier Acceptance Register 3        */
#define reg_CANIDMR0(x) (*((CAN_port)x + 0x14))   /* Identifier Mask Register 0              */
#define reg_CANIDMR1(x) (*((CAN_port)x + 0x15))   /* Identifier Mask Register 1              */
#define reg_CANIDMR2(x) (*((CAN_port)x + 0x16))   /* Identifier Mask Register 2              */
#define reg_CANIDMR3(x) (*((CAN_port)x + 0x17))   /* Identifier Mask Register 3              */
#define reg_CANIDAR4(x) (*((CAN_port)x + 0x18))   /* Identifier Acceptance Register 4        */
#define reg_CANIDAR5(x) (*((CAN_port)x + 0x19))   /* Identifier Acceptance Register 5        */
#define reg_CANIDAR6(x) (*((CAN_port)x + 0x1A))   /* Identifier Acceptance Register 6        */
#define reg_CANIDAR7(x) (*((CAN_port)x + 0x1B))   /* Identifier Acceptance Register 7        */
#define reg_CANIDMR4(x) (*((CAN_port)x + 0x1C))   /* Identifier Mask Register 4              */
#define reg_CANIDMR5(x) (*((CAN_port)x + 0x1D))   /* Identifier Mask Register 5              */
#define reg_CANIDMR6(x) (*((CAN_port)x + 0x1E))   /* Identifier Mask Register 6              */
#define reg_CANIDMR7(x) (*((CAN_port)x + 0x1F))   /* Identifier Mask Register 7              */
#define reg_CANRXFG(x)  (  (CAN_port)x + 0x20 )   /* Foreground Receive Buffer               */
#define reg_CANTXFG(x)  (  (CAN_port)x + 0x30 )   /* Foreground Transmit Buffer              */



Now you can use the registers as if they were variables, like this:

reg_CANCTL0(CAN0) |= ...


The code will work on any ISO C compiler.
0 Kudos

766 Views
Piete
Contributor I
Hello,

I tried to use the code but it seems not to work.

The attachment files are can.h and can.c. Perhaps someone can have look at the code. I can not find the mistake. The code stopps at

Code:
char CANInitMode(unsigned char CANModule){    reg_CANCTL0(CANModule) |= 0x01;                 while( !CANTestInitStatus(CANModule) ); <- it stopps here     return 0;        }

char CANTestInitStatus(unsigned char CANModule)
{
    return reg_CANCTL1(CANModule) & 0x01; 
}

 I start the initialization with

Code:
   stCANInit.CSWAI= 0;     // Low power / normal in wait mode (1/0)   stCANInit.TIME= 0;      // Timer for time-stamp enable/disable (1/0)   stCANInit.CANE= 1;      // Enable MSCAN!   stCANInit.CLKsrc=0;    // Clock source: bus/oscillator (1/0)   stCANInit.LOOPB= 0;     // Loop back Mode for test (ja=1/nein=0)   stCANInit.LISTEN= 0;    // MSCAN is listen only (ja=1/nein=0)   stCANInit.WUPM= 0;      // Low Pas filter for wake up (ja=1/nein=0)      CANInit(500, stCANInit, CAN_MODULE); // Defined in can.h as CAN0

 






0 Kudos

766 Views
Lundin
Senior Contributor IV
Sorry for the late reply.

First of all, the CANE bit is one of the notorious "write-once" bits. This means that in normal single chip mode (without debugger attached), you can only write to it once, and after that the value written stays. This might cause various unintended errors.

Also, are you sure that the line setting INITAK in CANCTL0 is executed? I can't find any errors in your code, though I only looked through it briefly.

The line setting CANCTL1 looks rather fishy. I would disassemble that one and see what it actually does.

I know that the MSCAN initialization is a bit delicate: I always put the module in sleep mode before initializing it. I think this was advised in some Freescale errata to avoid problems in case the init code is called more than once in a program.

Here is how I do it:

  reg_CANCTL0(port) |= SLPRQ;                    /* sleep mode */
  reg_CANCTL0(port) |= INITRQ;                   /* init mode  */

    while((reg_CANCTL1(port) & SLPAK)==0)        /* wait until CPU enters sleep mode. */
    {
      ;
    }
   
   
    reg_CANCTL1(port) |= CLKSRC;                 /* clksrc=bus */

    /* set baudrate, filters & acceptance  registers etc... */

  reg_CANCTL0(port) &= ~SLPRQ;                   /* leave sleep mode   */
  reg_CANCTL0(port) &= ~INITRQ;                  /* leave init mode    */

  if(useRxInterrupt)                             /* if the interrupts are used */
  {
    reg_CANRIER(port) = RXFIE;
  }


  while ((reg_CANCTL1(port) & (SLPAK|INITAK)) > 0) /* wait until CAN is running */
  {
    ;
  }

0 Kudos

766 Views
Piete
Contributor I

Hello,

 

thank you for your help. I changed a few things but it still does not work.

 

The attachment files are my new can.h and can.c. It still does not work. the programm stopps here:

 

while((reg_CANCTL1(CANModule) & 0x02)==0)    <-- stops here        {    }

 

 

 

 

 I starts with: CANInit(500, CAN0);.

 

The value of CANModule in CANinit is 64dec 0x40hex. Is this right? I think it has to be 0x140!?

 

I can not find the mistake....

 

Best regards

 

0 Kudos