How can i put the entire interrupt routine into RAM?

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

How can i put the entire interrupt routine into RAM?

Jump to solution
779 Views
rxlin
Contributor I

I wrote a C code to use API as my system base timer, I want to relocate the interrupt service routine into RAM segment, but when debugging, I found the current_clock++ (a unsigned long variable) will invoke a function "_LINC"  which is locate in the ROM.

How can i put the entire interrupt routine into RAM?

c.PNG

asm.PNG

Labels (1)
Tags (3)
1 Solution
615 Views
stanish
NXP Employee
NXP Employee

Hi,

_LINC is the run-time function to perform increment of 32-bit (long) integer. Since there is no hw. instruction support for this operation this is done by a routine instead.

One solution is to copy and paste the file below into your local project:

"c:\Program Files (x86)\Freescale\CWS12v5.2\lib\hc12c\src\rtshc12.c"

Now you can adjust the function to be placed into your RAM section "RAM_CODE"

/*---------- Long INCrement ---------------------------------------------------*/

/* D:X = (D:X)+1  */

#ifdef __cplusplus
extern "C"
#endif
#pragma push
#pragma CODE_SEG RAM_CODE
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT

void _LINC ( void ) {
  asm {
        IBNE  D,done
        INX
  done: RTS
  }
}
#pragma pop

Change the link order so the linker now prefers to uses the source file instead of the ANSI library:

pastedImage_1.png

Build the project and check the map file - now both isrVapi and _LINC are located in RAM_CODE section.

MODULE:                 -- main.c.o --
- PROCEDURES:
     main                                    FE8000       E      14       2   .text       
     isrVapi                                   2100      14      20       1   RAM_CODE    
- VARIABLES:
     current_clock                             2119       4       4       4   .common     
MODULE:                 -- Start12.c.o --
- PROCEDURES:
     Init                                    FE800E      29      41       2   .text       
     _Startup                                  C000       F      15       0   .init       
- VARIABLES:
     _startupData                              C00F       6       6       3   .startData  
- LABELS:
     __SEG_END_SSTACK                          2100       0       0       1               
MODULE:                 -- rtshc12.c.o --
- PROCEDURES:
     _LINC                                     2114       5       5       1   RAM_CODE    
- VARIABLES:

The drawback of this approach is that if you perform long increment in any other place of your code it always calls the RAM instance of _LINC.

If you want to have two separate instances for RAM and FLASH you should probably replace the  C increment statement in your interrupt handler:

   current_clock++;

with a custom function call e.g.:

   current_clock=_LINC_RAM(current_clock);

And create your custom version of long increment function in RAM.

Hope it helps.

Stan

View solution in original post

2 Replies
616 Views
stanish
NXP Employee
NXP Employee

Hi,

_LINC is the run-time function to perform increment of 32-bit (long) integer. Since there is no hw. instruction support for this operation this is done by a routine instead.

One solution is to copy and paste the file below into your local project:

"c:\Program Files (x86)\Freescale\CWS12v5.2\lib\hc12c\src\rtshc12.c"

Now you can adjust the function to be placed into your RAM section "RAM_CODE"

/*---------- Long INCrement ---------------------------------------------------*/

/* D:X = (D:X)+1  */

#ifdef __cplusplus
extern "C"
#endif
#pragma push
#pragma CODE_SEG RAM_CODE
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT

void _LINC ( void ) {
  asm {
        IBNE  D,done
        INX
  done: RTS
  }
}
#pragma pop

Change the link order so the linker now prefers to uses the source file instead of the ANSI library:

pastedImage_1.png

Build the project and check the map file - now both isrVapi and _LINC are located in RAM_CODE section.

MODULE:                 -- main.c.o --
- PROCEDURES:
     main                                    FE8000       E      14       2   .text       
     isrVapi                                   2100      14      20       1   RAM_CODE    
- VARIABLES:
     current_clock                             2119       4       4       4   .common     
MODULE:                 -- Start12.c.o --
- PROCEDURES:
     Init                                    FE800E      29      41       2   .text       
     _Startup                                  C000       F      15       0   .init       
- VARIABLES:
     _startupData                              C00F       6       6       3   .startData  
- LABELS:
     __SEG_END_SSTACK                          2100       0       0       1               
MODULE:                 -- rtshc12.c.o --
- PROCEDURES:
     _LINC                                     2114       5       5       1   RAM_CODE    
- VARIABLES:

The drawback of this approach is that if you perform long increment in any other place of your code it always calls the RAM instance of _LINC.

If you want to have two separate instances for RAM and FLASH you should probably replace the  C increment statement in your interrupt handler:

   current_clock++;

with a custom function call e.g.:

   current_clock=_LINC_RAM(current_clock);

And create your custom version of long increment function in RAM.

Hope it helps.

Stan

615 Views
rxlin
Contributor I

Hi,  Stanislav Sliva,

      Thank you for your help!  On your suggestion, I modified my code to the following

#define lONG_INC(var)     ((uint16_t *)&var)[1]++;\
                          if(((uint16_t *)&var)[1] == 0){\
                              ((uint16_t *)&var)[0]++;\
                          }
#pragma CODE_SEG RAM_CODE
/*
** ===================================================================
**     Interrupt handler : isrVapi
**
**     Description :
**         User interrupt service routine. 
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/
__interrupt void isrVapi(void)
{
  /* Write your interrupt code here ... */
  
  VREGAPICL_APIF = 0x01U;              /* Reset interrupt request flag */
  lONG_INC(current_clock);
}
/* end of isrVapi */
#pragma CODE_SEG DEFAULT‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos