Asm code before C-coded Main() - Write to global var in Asm code?

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

Asm code before C-coded Main() - Write to global var in Asm code?

Jump to solution
3,422 Views
VincentV
Contributor I
I'm writing code for the HCS12 and before main is called, I have it set up to first call some assembly code to check the health of the HCS12.

After these tests run and main() is called, I want to make sure that the tests were successful.

I would like to be able to shove the test results into a global variable (which is declaried in my main.c), but I seem to be missing something.

In the assembly, I have:

XREF post_status

and I can use the instrution:

MOVW #$BEEF, post_status

without trouble.

in main.c, after my #includes, I have

typedef unsigned int uint16;
extern uint16 post_status;
uint16 post_status;

Now, this compiles but does not seem to produce the desired result of having 0xBEEF stored in post_status when checked in main()

Any thoughts as to what it would take to coax code warrior into doing what I want to do?!

Message Edited by IronTek on 05-12-200609:33 AM

Message Edited by IronTek on 05-12-200610:10 AM

Message Edited by IronTek on 05-12-200610:10 AM

Labels (1)
Tags (1)
0 Kudos
1 Solution
779 Views
CrasyCat
Specialist III

Hello

I assume you have defined your own application entry point (implemented in your assembly source file) and at the end you are jumping to _Startup.

Am I right?

Within the _Startup function, we are initializing all global variable with 0.
That means when you reach the main function, the variable post_Status is initialized with 0 again (and you will not see 0xBEEF there).

In order to make sure the startup code does not initialize variables with 0, you need to define them in a memory area defined as NO_INIT (rather than READ_WRITE).

So basically:

 1- Define the¨variable in a user defined segment using
     #pragma DATA_SEG myTestData
     uint16 post_status;
     #pragma DATA_SEG myTestData
 2- In the PRM file allocate the segment MyTestData in a NO_INIT memory area:

SEGMENTS 
   RAM = READ_WRITE 0x1000 TO 0x3FFD;
   RAM_2 = NO_INIT 0x3FFE TO 0x3FFF; 
  ...
END

PLACEMENT
   myTestData INTO RAM_2;
...
END

This should do it.

Alternatively instead of defining a user define segment, you can specify your variable is allocated at absolute address 0x3FFE in the following way:

      uint16 post_status @0x3FFE;
and modify the definition of RAM memory area in the PRM file as follows:

   RAM = READ_WRITE 0x1000 TO 0x3FFD;

This also works.

I hope this helps.

CrasyCat

View solution in original post

0 Kudos
4 Replies
779 Views
VincentV
Contributor I
you are correct about the entry point.

And thanks! This advice definitely solves my troubles!
0 Kudos
780 Views
CrasyCat
Specialist III

Hello

I assume you have defined your own application entry point (implemented in your assembly source file) and at the end you are jumping to _Startup.

Am I right?

Within the _Startup function, we are initializing all global variable with 0.
That means when you reach the main function, the variable post_Status is initialized with 0 again (and you will not see 0xBEEF there).

In order to make sure the startup code does not initialize variables with 0, you need to define them in a memory area defined as NO_INIT (rather than READ_WRITE).

So basically:

 1- Define the¨variable in a user defined segment using
     #pragma DATA_SEG myTestData
     uint16 post_status;
     #pragma DATA_SEG myTestData
 2- In the PRM file allocate the segment MyTestData in a NO_INIT memory area:

SEGMENTS 
   RAM = READ_WRITE 0x1000 TO 0x3FFD;
   RAM_2 = NO_INIT 0x3FFE TO 0x3FFF; 
  ...
END

PLACEMENT
   myTestData INTO RAM_2;
...
END

This should do it.

Alternatively instead of defining a user define segment, you can specify your variable is allocated at absolute address 0x3FFE in the following way:

      uint16 post_status @0x3FFE;
and modify the definition of RAM memory area in the PRM file as follows:

   RAM = READ_WRITE 0x1000 TO 0x3FFD;

This also works.

I hope this helps.

CrasyCat

0 Kudos
779 Views
nanoGeek
Contributor I
The C start code is probably initializing your variable to 0x00 after you store the 0xbeef code.
 
What I've done to avoid this is create a separate memory space in the LCF file:
 
in the MEMORY section, place the following:
 DATA_RESET (RW) : ORIGIN = 0x???, LENGTH = 0
And set ORIGIN to some unused RAM (I like to use the on-chip RAM for this if it is available)
 
Next, define the data section:
 .uninitialized_reset_data :
 {
   *(.ResetData)
  . = ALIGN(0x8);
 } > DATA_RESET
 
Finally, you need to declare the variable(s) (I usually put the declaration in the main.c file):
/********************************************************************/
/* RAM variables that are fixed for external access by application */
#pragma define_section ResetData ".ResetData" far_absolute RW
__declspec(ResetData) uint32 d0_reset;   // reset d0
__declspec(ResetData) uint32 d1_reset;   // reset d1
/********************************************************************/
 
This code works for coldfire, but I'm not sure how the pragma or __declspec translate to the HC12 compiler so you might have to translate a bit to get it to work on your platform.
 
Hope this helps,
 
Joe
 
0 Kudos
779 Views
VincentV
Contributor I
Well, I assume that the LCF file is the linker file?

But, I was thinking about it, and while I would prefer that the linker/compiler handle this for me, I suppose I could just store it myself.

So the first thing I thought of is that, in my linker file, two of the lines state (I'm working with an MC9S12E128):

line 5: RAM = READ_WRITE 0x400 TO 0x1FFF;
...
46: STACKSIZE 0x100


Okay, given this, I thought of putting one 16-bit word right below the bottom of the stack. This way the stack won't ever clobber it, and if the code/program data clobbers it, well, I have bigger problems.

What do you think of this?

Second, is there a way I can allocate 16-bits above the stack?

I was thinking of something like:

RAM = READ_WRITE 0x400 TO 0x1FFD;
_MCU_TEST = READ_WRITE 0x1FFE to 0x1FFF;

And then I could just write 16-bits to 0x1FFE.

Now, I must admit to being pretty green with this sort of development. Does anyone see why either of these approaches wouldn't work (putting it right under the stack or right over the stack with the suggested linker file changes)?

Thanks!
0 Kudos