The most common case in which we need to run the code from the stack memory is while programming the flash memory of certain microcontrollers. Especially Freescale microcontrollers MC9S08QE8 / MC9S08QE32 / MC9S08QE128

microcontrollers required that the internal flash memory should not be accessed while Erasing/Writing to the flash memory pages.

If the flash memory is accessed during the erase or write operations then the operation fails due to violation or access error. So Once you execute a flash erase or write command you need to wait for the operation to complete by checking a flag which indicates the status or command execution. This flag checking code needs to be placed in RAM and run from there without accessing the flash memory. To do this we will declare a buffer of 100 bytes on Stack and copy the flag checking code to that buffer and run the code from there.

// This type is used to declare variables of size of flash location.

// This is the size of one memory location of flash, its a 8 bit flash so using unsigned char

typedef unsigned char FlashDataType;

// This type is used to declare variables of size of flash address, Memory address is 16 bits so using unsigned short

typedef unsigned short FlashAddressType;

// Declare a function pointer which takes no arguments and returns a unsigned char value

typedef unsigned char (*pFuncType)(void);

// This function RamCode is the one which is to be copied to the stack and run. Its better to write the RAM code in assembly to avoid jump instructions that use absolute addressing. If you use C code then we dont know whether the compiler has used absolute addressing or relative addressing for loops or branching statements. However in new generation compilers options exist to enforce relative addressing for loops and branching insructions.

// Code that runs on the Stack.

unsigned char RamCode(void)

{

asm

{

//your assembly code here

}// asm end

 

return 1; // Return a value

}

// Dummy function to determine the function end. While copying the code we need to know from where to where we are copying the code, So this RamCodeEnd() is used to determine the end of RamCode.

void RamCodeEnd()

{

unsigned char i=0; i++;

}

// Buffer of 100 bytes in which the code is copied and run. This buffer can be allocated on the stack or heap, here its assumed to be allocated on stack

FlashDataType Buffer[RAM_CODE_SIZE];

// A function pointer that points to code that runs on Stack.

pFuncType pFunc;

// The below statements determine the size of the function in bytes by assuming that the RamCodeEnd function is allocated right after the RamCode. As an alternative we can use FunctionSize=sizeof(RamCode);

FunctionSize=( ((FlashAddressType) RamCodeEnd) - ( (FlashAddressType) RamCode) );

// Loop until the end of the function code.

for(Index=0;Index<=FunctionSize;Index++)

{

// Copy code to Buffer which is allocated on Stack /RAM

Buffer[Index] = *(( (FlashDataType*) ( ((FlashAddressType)RamCode )+Index)) );

}

// Set function pointer to point to the buffer which holds the code to be run on Stack.

pFunc=(pFuncType)(void*)&Buffer[0];

// Calling the RAM code

if((*pFunc)() == FAILURE)

{

// Handle return values here

} 

This example is for microcontrollers which use Von-Neumann architecture where in the same address space is divided between Data memory and Code memory or RAM and Flash




About the Author

is the author of this blog and is an Embedded systems design engineer by profession & Founder @ Valetron Systems Pvt Ltd


Email:This email address is being protected from spambots. You need JavaScript enabled to view it.

Find us on Google+

HIRE ME FOR YOUR PROJECT AS A FREELANCER

 

EasyEDA: Free Circuit Design Software

  • Easy Schematic Capture
  • Powerful Circuit Simulation
  • Online PCB design

Design Your Circuit and PCB here:

https://easyeda.com/editor

Cheap PCB Manufacturing