zeroing .bss in IAR with non-standard code

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

zeroing .bss in IAR with non-standard code

2,775 Views
ryanlush
Contributor IV

I have a bootloader that loads code into RAM at runtime. I have the ramcode linking and executing as I would expect but I still need to manually clear the .bss section.

Here is my linker script

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x20007000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x20000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x20007000;
define symbol __ICFEDIT_region_RAM_start__ = 0x1FFF0000;
define symbol __ICFEDIT_region_RAM_end__   = 0x20000000;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000;
define symbol __ICFEDIT_size_heap__   = 0x1000;
/**** End of ICF editor section. ###ICF###*/

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_region_ROM_start__ { readonly section .init };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        block CSTACK, block HEAP };

And here is my startup code

extern int main(void);
extern int __vector_table[];

#pragma location=".init"
__interwork int __low_level_init(void)
{
 
    char * from = __section_begin(".bss");
    char * to = __section_end(".bss");
    
    memset(to, from , 0x00);
    
    memcpy(__vector_table, (unsigned char *)ROM_VECTOR_LOCATION, VECTOR_TABLE_SIZE);
 
    SCB_VTOR = (unsigned int) & __vector_table;
 
    main();
 
    SCB_VTOR = (uint32_t)ROM_VECTOR_LOCATION;
    
}

but the .bss section doesn't really seem to exist in the context I'm trying to use it. I get the following error.

Error[Pa053]: section/block has not been declared using #pragma section/segment

How do I "define" the .bss section so that the start/end address is available to me in my C code.

Labels (1)
0 Kudos
5 Replies

1,884 Views
mjbcswitzerland
Specialist V

Ryan

Try

#pragma segment=".bss"

and

unsigned char *start_of_bss =__sfb(".bss");

unsigned char *end_of_bss =__sfe(".bss");

Regards

Mark

P.S. I use __iar_program_start() as entry point in all cases since it then initialises .bss. It doesn't harm other things because it will see that initialised variables are at the same location as this values and so just jumps these parts. It then calls (your) main() when finished.

P.P.S. Your code is possibly only missing the
#pragma segment=".bss"
part (sfb() is just the assembler version of __section_begin)

0 Kudos

1,884 Views
ryanlush
Contributor IV

Mark,

I'm having a hard time understanding your P.S. comment but I think its something I need to do. I have a global variable initialized to 1 but I see it takes on all kinds of values. I believe this is because the .data section is not being copied to RAM.

What must I do to make __iar_program_start() as the entry point? I want that code to live at 0x20000000 but that's the reset handler if I leave things as the default.

I really appreciate all your help. No one in my company has done this before so you and Google have been my only friends.

0 Kudos

1,884 Views
mjbcswitzerland
Specialist V

Ryan

Whether you need to initialise statics depends on how they are located - if you use the initilisation values directly as variables there is no need to copy them and less RAM is needed. However, this is not that practical for RAM debugging since the code needs to be reloaded each time it is reset so that the initial values are returned again - for your application it may however be efficient.

The linker script that I showed is suitable for RAM debugging and I don't actually know whether IAR allows the other technique (at least I don't remember trying to do it with IAR). In any case, I use __iar_program_start() to allow it to initialise all that it needs to.

In case you continue having difficulties contact me at "mark (at) utasker.com" and we can do a remote desktop session so I can see what your present code is doing and show you what may need to be modified. I work as a consultant and trainer to many companies developing Kinetis based parts but offer a free 45 minute session to new customers. This should be adequate to solve your issue so it won't cost anything.

Regards

Mark

0 Kudos

1,884 Views
ryanlush
Contributor IV

Well something is missing because variables initialized to non-zero values

take on random values rather than the values I initialized them as.

I still don't understand how I force __iar_program_start() to be the entry

point without using the reset vector. Ive already disabled the watchdog in

the bootloader so I don't want to let the reset handler do it again in the

ramcode.

On Mon, Jan 22, 2018 at 8:27 PM, mjbcswitzerland <admin@community.nxp.com>

0 Kudos

1,884 Views
ryanlush
Contributor IV

Mark,

You're my hero.

On Mon, Jan 22, 2018 at 12:37 PM, mjbcswitzerland <admin@community.nxp.com>

0 Kudos