Code Warrior C Compiler issue

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

Code Warrior C Compiler issue

2,774 Views
MagnaDon
Contributor I

I am wondering if anybody can tell me why the following code will not work????

 

 

First, I have a function that returns an unsigned long as follows.  This function works with no problem.

 

unsigned long GetSysMSec(void){
  return(SystemClock);
} //End unsigned long GetSysMSec(void)

 

 

The problem is when I try to implement the function in the following two ways.

 

1) assigning to a variable and adding an offset within the same line:

 

//This does not work 

DelayTime = GetSysMSec() + 2000;

 

//This works

DelayTime = GetSysMSec();

DelayTime += 2000;

 

 

DelayTime is a variable of type unsigned long.

 

2) using the function in a comparison statement:

 

if(DelayTime <= GetSysMSec()){
      //Do Things
}

 

For some reson this always evaluates to true, even when I set DelayTime to a value much greater than the return from GetSysMSec()

 

Any help would be appreciated,  I am not certain if there is a compiler setting I need to look at or if there is just an issue with the compiler itself.  The code I have shown above works just fine on other platforms like my Keil Compiler used on an 8051 core.

 

 

CodeWarrior information:

Code Warrior IDE version   5.9.0

Build                              2330

 

 

 

 

 

 

Message Edited by MagnaDon on 2009-02-18 05:35 PM
Labels (1)
0 Kudos
11 Replies

956 Views
CompilerGuru
NXP Employee
NXP Employee

Which target Architecture are you using? Which product version?

IDE 5.9, build X tell me which editor you are using :smileywink:

 

Also according to the text you do not have an issue with the GetSysMSec function but with the uses of it.

Can you provide a full sample which shows what is not working.

 

As guess before I see the full sample, make sure you do not do any implicit parameter declarations.

In C undeclared functions return an int, so that's not compatible with the GetSysMSec signature.

Do you get any warnings when compiling your code?

 

Also what does "//This does not work" mean? Do you get wrong values? If so what values do you get,

what do you expect?

 

Daniel

0 Kudos

956 Views
MagnaDon
Contributor I

Here is more detail about my problem,  First I want to focus on issue 1, adding an offset to the return value.

 

Information on the compiler:

 

ANSI-C/cC++ Compiler for HC08 V-5.0.24 Build 7134, May 15 2007

 

Common Module V-5.0.8, Date May 15 2007

User Interface Module, V-5.0.25, Date May 15 2007

ANSI-C/cC++ Front End, V-5.0.6, Date May 15 2007

Tree CSE Optimizer, V-5.0.1, Date May 15 2007

Compiler Common Module, V-5.0.1, Date May 15 2007

Generic ICG Back End V-5.0.2, Date May 15 2007

Compiler Back Common, V-5.0.2, Date May 15 2007

HC08 ICG Back End V-5.0.24, Date May 15 2007

Encryption Module, V-5.0.3, Date May 15 2007

 

Info on the Target:

 

The code is targeted toward a MC68HC908QY4 8 bit micro.

 

 

Here are the code files.

 

SysClock.c

-------------------------------------------------------------------------------------------------

/*****************************INCLUDE*******************************/
#include  "MC68HC908QY4.h"
#include  "SysClock.h"

 

 

 

/*****************************Variables******************************/
static unsigned long SystemClock = 0;

 

/*****************************Defines********************************/
#define emulator

 

 


/*******************************CODE*********************************/
void SysClockInit(void){
  SystemClock = 0;
 
  //Setup the overflow counter for 10 milliseconds
  #ifdef emulator
    TMOD = 14050;
  #else
    TMOD = 32000;
  #endif
 
  //Setup the TSC register
  TSC_TSTOP = 0;
  TSC_TOF = 0;
  TSC_TSTOP = 1;
  TSC_TRST = 1;
  TSC_TOIE = 1;
  TSC_TSTOP = 0;
   
} //End void SysClockInit(void)


unsigned long GetSysMSec(void){
  return(SystemClock);
} //End unsigned long GetSysMSec(void)

 

void interrupt VectorNumber_TIMOvr TimOverflow(void){
  SystemClock += 10;  
  TSC_TOF = 0;  
} //end void interrupt VectorNumber_TIMOvr TimOverflow(void)

 

-------------------------------------------------------------------------------------------------

 

 

SysClock.h

 

-------------------------------------------------------------------------------------------------

 #ifndef       __SysClock_h__

#define       __SysClock_h__

void SysClockInit(void);
unsigned long GetSysMSec(void);
void interrupt VectorNumber_TIMOvr TimOverflow(void);


#endif

 

-------------------------------------------------------------------------------------------------

 

 

main.c

-------------------------------------------------------------------------------------------------

/***************************************Defines*********************************/
#define emulator

 


/***************************************Includes**********************************/
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include  "TypeDefs.h"


/******************************Module Includes***********************************/
#include  "main.h"
#include  "SysClock.h"
//#include  "PWM.h" 
//#include  "Display.h"


/***********************************Variables**************************************/
float tmpDC;
static unsigned long DelayTime;

/*************************************CODE*****************************************/

 

/*********************************************************************************/
/*********************************************************************************/
/*main                                                                           */
/*********************************************************************************/
void main(void) {

  asm{
    rsp
  }   
 
  initCPU();
  
  asm{
    rsp
  }   
 
  EnableInterrupts;   
  SysClockInit();
  //PWMInit();
 
 
  
  //MainLoop
  while(1){  
  
   DelayTime = GetSysMSec() + 2000;  
     
  }//End MainLoop
   
                  
} /* end void main(void)*/
/*********************************************************************************/
/*********************************************************************************/
/*********************************************************************************/

 

 


/*********************************************************************************/
/*initCPU                                                                        */
/*********************************************************************************/

void initCPU(void){


    
  //setup the config registers
  CONFIG2 = 0x00;
  CONFIG1 = 0x39; 
 
 
  #ifdef emulator
    OSCTRIM = 0x00;
  #else   
    //trim the oscillator
    OSCTRIM =  Optional;
  #endif  
 
 
  //Ram test
  asm{
RAM_TST:
   clrh        ; Clear index register H
   lda  #$FF    ; Load accum with test pattern

RAM_0:
   ldx  #0x80  ; Load index register with beginning of RAM address

RAM_1:
   sta  ,X     ; Store test pattern in RAM location
   incx        ; Increment RAM location
   cpx  #$FE    ; If index register not at last RAM location,
   bcs  RAM_1    ; Then continue to load RAM with test pattern
   ldx  #$80    ; Else, check that RAM location holds correct test pattern

RAM_2:
   cmp  ,X      ; If RAM location doesn't hold correct test pattern,
   bne  RAM_TST   ; Then try loading RAM locations again with original test pattern (Watchdog will timeout if RAM error)
   incx        ; Increment RAM location
   cpx  #$FE    ; If index register not at last RAM location,
   bcs  RAM_2    ; Then continue testing RAM test pattern
   cmp  #$00    ; If test pattern equal to zero,
   beq  RAM_X    ; Then exit routine 
   sub  #$55    ; Else, subtract pattern for new test pattern
   jmp  RAM_0    ; Load RAM with new test pattern
RAM_X:   
  } //end asm Ram Test 
   
} /* end void initCPU(void) */

/*********************************************************************************/
/*********************************************************************************/

 

-------------------------------------------------------------------------------------------------

 

main.h

-------------------------------------------------------------------------------------------------

void initCPU(void);

-------------------------------------------------------------------------------------------------

 

 

So I have these 4 files

main.c

main.h

SysClock.c

SysClock.h

 

SysClock.c contains a timer overflow interrupt that generates a 10ms clock stored within the unsigned long variable SystemClock, which is initialized to 0.  The function GetSysMSec() is also a part of this file and simply returns SystemClock.

 

During emulation using the FSICEBASE I get the following:

 

When I put the following snippit of code whithin the main loop

 

DelayTime = GetSysMSec();

 

DelayTime will follow SystemClock

 

SystemClock = 0

DelayTime = 0

 

SystemClock = 0x1E

DelayTime = 0x1E

 

 

But when I try to add an offset of 2 seconds

 

DelayTime = GetSysMSec() + 2000;

 

I get the following:

 

DelayTime is 0 just prior to the line call for the first time

DelayTime = 0x028407D0 is the return value when SystemClock is 0

 

I expect that DelayTime should be 0x000007D0.

 

Now as SystemClock is changing value for example when SystemClock reaches 0x0000008C (140mS)

The same line call

 

DelayTime = GetSysMSec() + 2000;

 

should assignd the value of 0x0000085C to DelayTime, instead I get DelayTime = 0x028407D0, the same value as before.  Nothing happens to DelayTime from this point forward no matter what the value for SystemClock is.

 

Now just as a little note, 0x0284 just happens to be the value of memory locations 0x0000 and 0x0001, which are registers set aside for PortA and PortB.

 

 

 

 

 

 

 

 

 

 

0 Kudos

956 Views
bigmac
Specialist III

Hello,

 

There seems to be a couple of major issues associated with your code. You have declared two static/global variables that I assume you are initializing using the ANSI initialisation process (within start08.c). This will occur prior to main() being called.

 

Within the function initCPU(), the RAM test assembly code then over-writes all of RAM, including the initialised variables and the stack. Under simulation, this caused failure due to an attempt to write to an unimplemented memory location during the DelayTime calculation.

 

A further serious problem is that you are using the RSP assembly instruction within main(). The stack pointer does not have a value of 0x00FF prior to this code. In fact the default PRM file places the stack immediately above the static/global variables, and the main() function call also allocates some stack space.

 

The expected results were obtained once the RAM test code and the RSP instructions were commented out.

 

The solution would seem to be that you could use the minimal initialisation option, rather than ANSI, within the project. You would then need to add the RAM test code within start08.c. RSP could be used here, if necessary. Your code would also need to explicitly initialise the static variables within main().

 

A couple of other issues -

  1. You have enabled interrupts prior to calling SysClockInit(), probably not a good idea since this sets up the TIM hardware.
  2. It is a good idea to appropriately clear the COP timer within the code, even if the COP may initially be disabled.
  3. You seem to have declared an, as yet unused float variable. The MCU you are using does not have sufficient resources to handle floating point operations.

Regards,

Mac

 

Message Edited by bigmac on 2009-02-20 02:41 PM
0 Kudos

956 Views
MagnaDon
Contributor I
That seems to clear things up.  I had originally changed the prm file to set the main() routine as vector 0, bypassing the startup code, but apparently it is needed.  anyway thank you.
0 Kudos

956 Views
bigmac
Specialist III

Hello,

 

The minimal startup code sets the stack pointer, and then jumps to main().  The RAM test should be placed directly within _Startup(), and not as a function call.  This means that no stack is currently in use prior to the RAM test, so the RAM may be freely over-written.

 

Regards,

Mac

 

0 Kudos

956 Views
CompilerGuru
NXP Employee
NXP Employee

I would suggest to add a volatile to SystemClock as this variable is accessed from the interrupthandle and from the main code.

The main loop shown is not actually using the value assigned to DelayTime. Therefore not writing to DelayTime is legal, though I'm not sure that's the issue you see. I would either use DelayTime or make DelayTime volatile too (this one just for/during debugging).

 

Appart from this, is could there be any stack space issues? How big is the stack, bit enought?

Also are the variables inside of the area touched by initCPU? If so they wont be 0 initialized anymore. Well that's not the issue though.


Daniel
0 Kudos

956 Views
djsimpson
Contributor III

Another issue will be in this routine.

 

unsigned long GetSysMSec(void){
  return(SystemClock);
} //End unsigned long GetSysMSec(void)

 

 

You have no guarantee that the interrupt function which changes the value of SystemClock does not execute during the reading of SystemClock. The HC08 can not read a long as an atomic operation, and the compiler generates code which calls the _COPY function, which if you look in the library source code, copies one byte at a time. If the value of SystemClock gets changed during the copy by the interrupt, then the returned value will be incorrect. 

 

This won't happen often, but it WILL happen.

 

David

 

 

 

 

 

 

0 Kudos

956 Views
J2MEJediMaster
Specialist I

Just a stab at troubleshooting here: the value 0x028407D0 that GetSysMSec() returns, does it match the address of GetSysMSec() in the output map?

 

---Tom

0 Kudos

956 Views
MagnaDon
Contributor I

No,  The first portion of the return value 0x0284 is the value of 0x0000 and 0x0001 the second half 0x07D0 is the value 2000 which I was expecting.

 

0 Kudos

956 Views
erooll
Contributor II

Hi. Try to cast the operators. like this...

 

DelayTime = (unsigned long)GetSysMSec() + (unsigned long)2000;

 

and...

 

if((unsigned long)DelayTime <= (unsigned long)GetSysMSec()){
      //Do Things
}

 

good luck.

0 Kudos

956 Views
MagnaDon
Contributor I
Tried casting with no luck.
0 Kudos