-1

I want to place parts of code in ITCM (using IAR). The manual (IAR ARM Development Guide), as I could find, has instructions only for general case when you put all the code in RAM. But my app does not fit in ITCM, so I need a way to specify which modules go to RAM.

I found the example with AN4667 which has a test for different configurations (project called "stm32f7_performances"), one of which is CodeInITCM+DataInDTCM. There is an .icf for this case which compiles fine.

But, for some reason, it starts to behave badly if some modules contain constants placed in code. I isolated the following minimum main.c file (see below) which produces warnings on linking which lead to unworking final hex image. My project includes just startup_stm32f756xx.s, main.c and the 5-RamITCM_rwRAM-DTCM.icf linker file from the example which I include below. Trying to build this, I get the following warnings:

Building:

Building configuration: Project - 5-RamITCM_rwRAM-DTCM 
main.c  
Linking 
Warning[Lp005]: placement includes a mix of sections with content (example "ro code section .text in main.o symbols: [SystemInit, main]") and sections without content (example "rw data section .rodata in main.o") 
Warning[Lp006]: placement includes a mix of writable sections (example "rw data section .rodata in main.o") and non-writable sections (example "ro code section .text in main.o symbols: [SystemInit, main]") 

Total number of errors: 0 
Total number of warnings: 2 

This is the minimal case just to illustrate the problem, so it lacks any hw init etc. When I build my real program and try to load/execute it, it fails to load correctly, so these warnings apparently are critical.

If I put all the code in Program_RAM_ITCM_region using "place in Program_RAM_ITCM_region { ro };" command in .icf file, it builds and runs good, but my real app's code size is larger than ITCM size, so I need to be able to select modules which go to ITCM.

Can anyone tell me the reason for this behavior and how to solve this issue?

Vladimir


main.c file:

    void SystemInit(void) {}
    
    volatile static int iii = 0;    
    
    void Test(char *s)
    {
      for (int i = 0; i < 10; i++) iii = s[i] ? 1:0;
    }
    
    int main(void)
    {
      Test("=======================================================\r\n");
    }

5-RamITCM_rwRAM-DTCM.icf file:

/*###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__ = 0x00200000;

/*= Code region(s) ===================================== */
/* -- Program region in internal Flash ----------------- */
define symbol __ICFEDIT_Program_In_FLASHTCM_start__    = 0x00200000;
define symbol __ICFEDIT_Program_In_FLASHTCM_end__      = 0x002FFFFF;
/* -- Program region in RAM ITCM ----------------------- */
define symbol __ICFEDIT_Program_In_RAM_ITCM_start__    = 0x00000000;
define symbol __ICFEDIT_Program_In_RAM_ITCM_end__      = 0x00003FFF;

/*= Data region(s) ===================================== */
/* RAM -- +RW +ZI region ------------------------------- */
/* The RW and Zero Initialized data will be in RAM-DTCM (0x4000 = 16k)
  All global variables will be located in this section. */
define symbol __ICFEDIT_region_RW_ZI_RAM_DTCM_start__  = 0x20000000;
define symbol __ICFEDIT_region_RW_ZI_RAM_DTCM_end__    = 0x20003FFF;

/* RAM -- STACK region --------------------------------- */
/* The Stack of the main application will be in RAM-DTCM (0x4000 = 16k)
 All internal variables of called functions will be located in this region. */
define symbol __ICFEDIT_region_STACK_RAM_DTCM_start__  = 0x20004000;
define symbol __ICFEDIT_region_STACK_RAM_DTCM_end__    = 0x20007FFF;

/* RAM -- HEAP region ---------------------------------- */
/* The Heap of the main application will be in RAM-DTCM (0x8000 = 32k)
 All dynamic allocations data got by malloc, realloc, calloc... will be located
 in this region.*/
define symbol __ICFEDIT_region_HEAP_RAM_DTCM_start__   = 0x20008000;
define symbol __ICFEDIT_region_HEAP_RAM_DTCM_end__     = 0x2000FFFF;

/*= STACK and Heap Sizes =============================== */
define symbol __ICFEDIT_size_cstack__ = 0x4000;  /* 16k */
define symbol __ICFEDIT_size_heap__   = 0x8000;  /* 32k */
/**** End of ICF editor section. ###ICF###*/

/*= Memory regions definition ========================== */
define memory mem with size = 4G;
define region Program_FlashAXI_region  = mem:[from __ICFEDIT_Program_In_FLASHTCM_start__ to __ICFEDIT_Program_In_FLASHTCM_end__];
define region Program_RAM_ITCM_region  = mem:[from __ICFEDIT_Program_In_RAM_ITCM_start__ to __ICFEDIT_Program_In_RAM_ITCM_end__];
define region RAM_DTCM_RW_ZI_region    = mem:[from __ICFEDIT_region_RW_ZI_RAM_DTCM_start__ to __ICFEDIT_region_RW_ZI_RAM_DTCM_end__];
define region RAM_DTCM_STACK_region    = mem:[from __ICFEDIT_region_STACK_RAM_DTCM_start__ to __ICFEDIT_region_STACK_RAM_DTCM_end__];
define region RAM_DTCM_HEAP_region     = mem:[from __ICFEDIT_region_HEAP_RAM_DTCM_start__ to __ICFEDIT_region_HEAP_RAM_DTCM_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, //ro
  /* Copy also the constants of these objects in RAM-ITCM */
    ro object  main.o
};               

do not initialize  { section .noinit };

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

place in Program_FlashAXI_region { readonly };

//place in Program_RAM_ITCM_region { ro };

place in Program_RAM_ITCM_region {
  section .text object main.o,
  /* Place also const data in ITCM-RAM. */
  section .rodata object main.o,
};

place in RAM_DTCM_RW_ZI_region  { readwrite };
place in RAM_DTCM_STACK_region  { block CSTACK };
place in RAM_DTCM_HEAP_region   { block HEAP }; 
wowa
  • 1
  • 3
  • You are trying to solve some kind of X-Y problem. Why do you want to run the whole app from the RAM? It makes sense to place very time critical routines there (for example interrupt handler if latency of 4-5 clocks caused by the FLASH matters) otherwise it makes no sense at all – 0___________ Dec 21 '21 at 21:19
  • @0___________: I actually wrote that I don't want to put all the code there. There is no problem with the linker to put all the code - in this case it builds ok, but I don't have so much memory. The problem occurs namely when I try to move into ITCM only ISR and main program loop. And yes, I want to put in RAM all the parts which are performed constantly, it makes sense in my case, believe me). – wowa Dec 22 '21 at 13:54
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Dec 29 '21 at 16:02

1 Answers1

0
define symbol __RAM_func_start__ = 0;  //ITC start
define symbol __RAM_func_end__ = 0x10000;//start + 64k
define region RAM_func_region = mem:[from __RAM_func_start__ to __RAM_func_end__];

define block RamCode {section .textrw};
place in RAM_func_region { block RamCode };
initialize by copy {readwrite};

And mark functions __ramfunc for example

__ramfunc int main(void)
{
    /* ..... */
}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • Thanks for the advice! I added this to .icf and made main() and Test() __ramfuncs, and it builds almost good, but gives a "Warning[Ta022]: Possible rom access () from within a __ramfunc function". It's obviously because linker does not place literal in RAM. Is it possible to force it to do so? Another drawback with this method is that if I want to place some HAL funcs in RAM, I need to modify HAL sources. It is strange that you cannot simply say the linker to put in RAM just needed stuff. – wowa Dec 23 '21 at 12:36
  • You cant silence this warning. This warning is issued because very often code in RAM is used for example to program FLASH and FLASH can not be available at this point. It should work OK. – 0___________ Dec 23 '21 at 15:35
  • *`It is strange that you cannot simply say the linker to put in RAM just needed stuff`* How can compiler know it? You need to tell him. I would not use HAL functions in places where you have to run from RAM. You should do it on the registers level. – 0___________ Dec 23 '21 at 15:37
  • Yes, I understood that it should work, but I meant that it would be better if IAR put those constants in RAM too. Can I force it somehow? – wowa Dec 23 '21 at 17:50
  • "How can compiler know it?" - I meant they (IAR) obviously have some means for it in .icf file, not in c/c++ at the source level. – wowa Dec 23 '21 at 17:52
  • *"I would not use HAL functions in places where you have to run from RAM. You should do it on the registers level."* - In general agree, but the same relates to some lib funcs like double-int conversions and DSP funcs which I need and have no access to sources. – wowa Dec 23 '21 at 17:58
  • I do not think that you need DSP or double function in RAM :). As I wrote above you probably are trying to sort out not existing problem. Generally speaking why some interrupts handlers sometimes have to be placed in the SRAM - because the time of fetching the code from FLASH and feeding the pipeline will be too long. Instead 12 clocks it will be about 20. 8 clocks using 480MHz micro is 0.17ns. If this time makes any difference - place it in the RAM. If not - do not. – 0___________ Dec 23 '21 at 18:06
  • When you run "normal" code (calculating something for example) you will not get a huge speed increase as code cache and ART accelerator work very well for those micros. – 0___________ Dec 23 '21 at 18:08