This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I am programming a system, where I want to position into RAM
- the program parts that are urgent (ISR)
- the program parts which perform the biggest part of runtime
- intermediate values and constants
So I have to copy these values from FRAM to RAM on each power out.
In assembly language I would use absolute addresses and relative jumping etc., a relative complex handling.
Does anyone have any info or examples, especially in C with info how to handle that with IDE.
You can do this by creating one or more RAM sections in the Linker Command File;
UNION RUN = RAM1 { .RAM1_functA : LOAD = FLASH2 | FLASH1B1, LOAD_START(_RAM1_functALoadStart), LOAD_END(_RAM1_functALoadEnd), LOAD_SIZE(_RAM1_functALoadSize), RUN_START(_RAM1_functARunStart) .RAM1_functB : LOAD = FLASH2 | FLASH1B1, LOAD_START(_RAM1_functBLoadStart), LOAD_END(_RAM1_functBLoadEnd), LOAD_SIZE(_RAM1_functBLoadSize), RUN_START(_RAM1_functBRunStart) }
And the following example program speaks for itself;
extern void _RAM1_functALoadStart, _RAM1_functARunStart, _RAM1_functALoadSize; #pragma CODE_SECTION(InhibitTimer, ".RAM1_functA") void InhibitTimer (void) { TA0CCTL0 = 0; __delay_cycles(1000000); TA0CCTL0 = CCIE; } void main (void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT memcpy (&_RAM1_functARunStart, &_RAM1_functALoadStart, _symval(&_RAM1_functALoadSize)); // Flash LED by Timer P1DIR |= 0x01; // P1.0 output TA0CCTL0 = CCIE; // CCR0 interrupt enabled TA0CCR0 = 50000; TA0CTL = TASSEL_2 + MC_1 + TACLR; // SMCLK, upmode, clear TAR __bis_SR_register(GIE); while (1) { __delay_cycles(1000000); InhibitTimer(); } } // Timer0 A0 interrupt service routine #pragma CODE_SECTION(TIMER0_A0_ISR, ".RAM1_functA") #pragma vector=TIMER0_A0_VECTOR __interrupt void TIMER0_A0_ISR(void) { P1OUT ^= 0x01; // Toggle P1.0 }
Leo is correct and shows one way of moving code from one memory location to another (e.g. FRAM to RAM).
The linker also supports a "Copy Table" feature that simplifies the code a little bit. As with the previous example, this requires editing the linker command file. Here, the syntax is slightly different in that you specify a "table" to hold the address & length information:
UNION { .f1 : {} load = FRAM, table ( func1_copy_table ) .f2 : {} load = FRAM, table ( func2_copy_table ) } run = RAM
This generic example shows two functions (each in their own code section ".f1" and ".f2") being linked into FRAM, but to be run from RAM. Notice that the linker table() function defines a symbol (e.g. func1_copy_table) that points to a structure including the load address, run address, and length of the output section.
The compiler runtime support library includes a simple function call copy_in() for accessing the copy addresses, as well as invoking memcpy() to actually move the contents pointed to by the table.
The main code (shown below) for this generic example includes a reference to the:
#include "driverlib.h"
#include <cpy_tbl.h>
#include "hal.h"
void func1();
void func2();
extern COPY_TABLE func1_copy_table;
extern COPY_TABLE func2_copy_table;
void main()
{
// Stop watchdog timer
WDT_A_hold( WDT_A_BASE );
// Initialize GPIO
initGPIO();
copy_in( &func1_copy_table );
func1();
copy_in( &func2_copy_table );
func2();
}
#pragma CODE_SECTION (func1, ".f1")
void func1(void) {
GPIO_setOutputHighOnPin( LED1_PORT, LED1_PIN );
}
#pragma CODE_SECTION (func2, ".f2")
void func2(void) {
GPIO_setOutputHighOnPin( LED2_PORT, LED2_PIN );
}
In the end, this code is quite similar to that provided by Leo; but simplifies the creation and access of the run/load addresses using the linker's Copy Table feature. You can find more info on this feature in the following two documents:
Take Care,
Scott
**Attention** This is a public forum