Topic : Manually copying INRAM functions to RAM using symbols

Forum : ST7/STM8

Original Post
Post Information Post
September 17, 2012 - 11:53am
Guest

I am using a number of the stm8s_flash.c functions as INRAM functions.

Because the flash function code will be stored in a space beyond 0x10000 and the global variable initialisation startup code doesn't use far addressing, I am trying to copy these INRAM functions form their flash program storage address to RAM manually.

I am using your example from the compiler manual which is also more or less reproduced in comments in the stm8s_flash file.

I have created a seperate c and h file called InRAMCopy.c & InRAMCopy.h

Here's an example of the declaration for Flash_EraseByte function address and size symbols:

extern int __address__FLASH_EraseByte; // Symbol holding the flash address
extern int __size__FLASH_EraseByte; // Symbol holding the function size

Heres an example of the memcpy: I'm using MEMCPY which gets redefined as fmemcpy

void CopyInRAMFunctions(void)
{
     // Copy the function code using memcpy()
     MEMCPY(FLASH_EraseByte, // RAM destination address
     (void far*)&__address__FLASH_EraseByte, // Flash source address
    (int)&__size__FLASH_EraseByte); // Code size of the function
}

Here's how its written in stm8s_flash.c:

IN_RAM(void FLASH_EraseByte(uint32_t Address))
{
    /* Check parameter */
    assert_param(IS_FLASH_ADDRESS_OK(Address));
    
    /* Erase byte */
   *(uint8_t PointerAttr*) (uint32_t)Address = FLASH_CLEAR_BYTE; 

}

and from the stm8s_flash header:

IN_RAM(void FLASH_EraseByte(uint32_t Address));

The linker gives this error:

***ERROR 100 : UNRESOLVED EXTERNAL
SYMBOL : __address__FLASH_EraseByte(INRAMCOPY)

Is there something about the way INRAM is used if you're doing the copy manually or maybe does the copy code have to exist in the same c file as the INRAM functions? OR have I done something really silly that I haven't spotted yet?
In your example, the function, the function call, the address and size symbols and the ram copy function appear as though they are all in the same file. Is this important or can my copy function be somewhere else entirely as I had done?

JD

Replies
Post Information Post
+1
0
-1
September 17, 2012 - 2:56pm
Raisonance Support Team

JD,

This issue appears when you don't have a Data Initialization segment.
It comes if you don't specify a main() or if you're using your own startup without calling the
data initialization.

Stéphane

+1
0
-1
September 18, 2012 - 3:51am
Guest

Stéphane,

Maybe i need to expand on my brief desription above.

No, i dont have a main().
Yes, I understand that this means that the startup_STM8.asm wont get called.
Yes, I understand that the call the the global variable initialisation and INRAM function copy normally happens there.
Yes, I understand that I have to create my own segment and my own reset vector jump which I've done.

Why am I doing it this way? Because your global variable initialisation code appears to only use 16 bit addressing when it copies variables from flash to RAM.
That is a problem becasue all my code exists in an address space beyond 0x10000.
I did include it early on to see what it would do but i can see by assembly stepping with the debugger that the addresses used have been shortened to 16 bit so the address is wrong.

So I am leaving out your global variable intialisation code. We don't have a problem initialising global variables manually ourselves. What I do need to try to do is manually copy some flash_stm8.c INRAM functions to RAM. Which I should be able to do if the linker is creating these size and address symbols.

Will the linker still create the symbols __address__function and __size__function if I'm doing this manually?
The problem I see here with the errors that I'm getting is that those symbols don't exist as far as the linker seems to be concerned?

hence the error:

***ERROR 100 : UNRESOLVED EXTERNAL
SYMBOL : __address__FLASH_EraseByte(INRAMCOPY)

JD

+1
0
-1
September 18, 2012 - 9:56am
Raisonance Support Team

JD,

To initialize variables and in RAM routines, the "startup" uses a segment called ?PR?STATINIT
The __address__function is an address in this segment. If this segment doesn't exist, the linker isn't
able to retrieve it.
If it isn't find by the linker, it is because, you don't make any reference to it thru the ?C_INITSEGSTART
symbol.

Stéphane

+1
0
-1
September 18, 2012 - 11:58am
Guest

Thanks for the prompt reply.

I was thinking that maybe the linker had a symbols available for all sizes of all functions but it sounds like you'd have to get that segment included by calling the global variable init function.

From what I've seen, ?PR?STATINIT doesn't get included if i don't call ?C?InitData.

Is there a way that i can include ?PR?STATINIT to use it's resources without calling ?C?InitData?

I don't really want to have to call it if I don't have to. If there's no other way around it, I might call ?C?InitData, let it do its thing just so I can have the __address__function and __size__function resources, and then do my own initialisation and inram function copy afterwards.

Thanks for your attention,
JD

+1
0
-1
September 18, 2012 - 1:31pm
Raisonance Support Team

Add an assembly file to your project with the following code:

EXTRN CODE (?C_INITSEGSTART)

ASMSEG SEGMENT CODE
RSEG ASMSEG

LDW X, #?C_INITSEGSTART

END

The data init segment will be linked and __address__function will therefore be available.

Stéphane