Author Topic: SAMV71 how to execute function from ram (harmony 3, xc32 v4.00 compiler) SOLVED  (Read 1339 times)

0 Members and 1 Guest are viewing this topic.

Offline Gabri74Topic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: it
Hi all, I could use some help because I'm really struggling here  |O

I've a project based on the SAMV71Q21B, built using MPLAB-X and Harmony 3 for BSP and drivers code generation.

The problem is that I can't figure out how to run a function from ram (I need to read the unique ID from flash and the access must be done from ram because when
accessing that specific flash controller register no code can be fetched from flash).
Moreover, all the examples and responses on github or forums that I've found refer to GCC compiler, not XC32, and the linker scripts and startup code are quite different for the two:
- in the GCC linker script there is a 'relocate' region defined, but not on the XC32 linker
- in the GCC startup code there is the relevant memory initialization code that copies the relocate section to ram, but not on the XC32 startup version
- in the XC32 startup version there is a call to a '__pic32c_data_initialization()' which I suspect could be the one that copies the relocatable code, but it's a closed library function so I can't tell.

I've started adding this attribute in front of the relevant function:
Code: [Select]
__attribute__ ((ramfunc,section(".ramfunc"),long_call, unique_section,noinline)) void utils_base_unique_id(uint8_t *uid)
{ [READ ID FROM FLASH CODE] }

but when compiling a get a bunch of errors I don't understand, it seems like the linker is moving other unrelated code to the relocate section:
Code: [Select]
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: Link Warning: attributes for input section '.RAMFUNC$.__stub' conflict with output section '.RAMFUNC$'
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .text.CLK_MainClockInitialize%449 LMA [004a264c,004a26df] overlaps section .text.sys_init%448 LMA [004a25b4,004a2657]
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .bss.resp.13237%53 VMA [20420e7c,20420f03] overlaps section .RAMFUNC$ VMA [20420dec,20420e8f]
Link Error: can't load section .RAMFUNC$ contents
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: BFD (Microchip xc32 v4.00) 2.32.0.20190703 internal error, aborting at /data01/build/bamboo/xml-data/build-dir/M32DEV-BGT38-JOB1/src/gcc-8-merge/binutils/bfd/elf32-pic32c.c:324 in bfd_pic32_process_data_section

I've tried to add the missing relocate section to my linker script (copied from the gcc script) but I get a similar but different error:
Code: [Select]

/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: Please report this bug.
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: Link Warning: attributes for input section '.data.uxCriticalNesting' conflict with output section '.relocate'
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: Link Warning: attributes for input section '.ramfunc.utils_base_unique_id.__stub' conflict with output section '.relocate'
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .dinit%204 LMA [00485610,0048773f] overlaps section .relocate LMA [00484390,0048561f]
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .text.CLK_MainClockInitialize%414 LMA [004a38cc,004a395f] overlaps section .text.sys_init%413 LMA [004a3834,004a38d7]
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .bss.ucHeap%1 VMA [20401a80,2040ba7f] overlaps section .relocate VMA [20400800,20401a8f]
Link Error: can't load section .data.uxCriticalNesting contents
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: BFD (Microchip xc32 v4.00) 2.32.0.20190703 internal error, aborting at /data01/build/bamboo/xml-data/build-dir/M32DEV-BGT38-JOB1/src/gcc-8-merge/binutils/bfd/elf32-pic32c.c:324 in bfd_pic32_process_data_section

/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: Please report this bug.

Does anyone have a sample code for th V71 or another SAM using XC32 and running a function from ram?
Any help really appreciated   :D

Attached my startup code (vanilla) and my slightly modified linker script with the ramfunc section added commented out (renamed to TXT because .ld is not allowed)
« Last Edit: July 10, 2024, 09:30:20 am by Gabri74 »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
It is in the XC32 compiler manual. You need to use __ramfunc__ , not just the attribute because XC32 uses a customized linker.
Alex
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15029
  • Country: fr
XC32 uses a customized linker.

Which I found out the hard way at some point when I was working with PIC32. I was expecting it to just be binutils ld, with the usual parameters. But their customized linker takes additional parameters, from what I remember. :popcorn:
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
It takes a lot of random stuff that arguably does not need to be there. But one thing it has over the standard ld is the flowaround placement. You can fix some functions/variables to some addresses and the rest will be freely placed.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
... I need to read the unique ID from flash and the access must be done from ram ....
How do you plan to do this?
Code: [Select]
my_clever_ram_func()
{
call(interrupts_in_flash);
call(readbyte_func_in_flash);
call(outstring_func_in_flash);
......
}
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
What is this code?

Reading UID on this device is a pretty standard procedure. A ramfunc with disabled interrupts is a standard way to do that. The only issue here is that XC32 requires a proprietary way of placing things in SRAM instead of a standard section attribute.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
What is this code?
I would be very glad to see your code.

I know what needs to be done. But the right advice can turn into long-term training, which I don’t want.
« Last Edit: July 08, 2024, 10:47:43 pm by Postal2 »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
Code: [Select]
__longramfunc__  void read_uid(uint32_t *uid)
{
  uint32_t *flash = (uint32_t *)IFLASH_ADDR;

  __disable_irq();

  EFC->EEFC_FMR |= EEFC_FMR_SCOD;

  EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
  while (EEFC_FSR_FRDY == (EFC->EEFC_FSR & EEFC_FSR_FRDY));

  for (int i = 0; i < 4; i++)
    uid[i] = flash[i];

  EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SPUI;
  while (0 == (EFC->EEFC_FSR & EEFC_FSR_FRDY));

  EFC->EEFC_FMR &= ~EEFC_FMR_SCOD;

  __enable_irq();
}

On 32 bit platforms it must be __longramfunc__. More of the XC32 nonsense.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
More of the XC32 nonsense.
Okay. This can be done by loading to flash with labels on begin and end, then dynamically load to predefined rwx-region and run.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
You would have to somehow generate a position independent code, what is not trivial. You can't take arbitrary code from the flash and copy it into the RAM and just run it.

Plus compilers supported ramfuncs since forever, so there is no real point in doing it manually.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
You can't take arbitrary code from the flash and copy it into the RAM and just run it.
Not right. See my example in topic below, where linker fills data. It can be done from code also by function address.

Plus compilers supported ramfuncs since forever, so there is no real point in doing it manually.
Why fill the RAM with unnecessary junk that runs once. This is bad form.
« Last Edit: July 08, 2024, 11:15:48 pm by Postal2 »
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15029
  • Country: fr
You would have to somehow generate a position independent code, what is not trivial. You can't take arbitrary code from the flash and copy it into the RAM and just run it.

Unless said function is located at a fixed address in RAM, and has been put in the corresponding section in the linker script. Then you don't need PIC?
Of course, that requires reserving a fixed area in RAM just for this.

Plus compilers supported ramfuncs since forever, so there is no real point in doing it manually.

What does "ramfunc" do exactly?
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
What does "ramfunc" do exactly?
See above, ataradov  kindly showed. Only r/w of registers and store string to RAM. Size of function is several bytes. Possible set label before return to assign size of function from code.
« Last Edit: July 09, 2024, 01:16:21 am by Postal2 »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
Unless said function is located at a fixed address in RAM, and has been put in the corresponding section in the linker script. Then you don't need PIC?
Of course, that requires reserving a fixed area in RAM just for this.
My comment was about temporarily relocating things to flash. Worrying about a few bytes of RAM on a device with 380K seems silly to me. And then you can also put that function at the bottom of the stack space and call it at the beginning of the program when this area is not used. Later it will be overwritten by the stack, of course.

What does "ramfunc" do exactly?
It physically places the code in the flash, but links it in a way that it could be executed from SRAM. It is placed in the .data section, so it is relocated to SRAM at the same time as initialized variables.

Doing that manually does not make any sense to me.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
Doing that manually does not make any sense to me.
And if I show how simple it is, will you change your mind?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
And if I show how simple it is, will you change your mind?
No, why would I? There is a well established method that works perfectly well.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
And if I show how simple it is, will you change your mind?
No, why would I? There is a well established method that works perfectly well.
Then teach your method to the topic author. This will prove how good this method is, especially for him.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11532
  • Country: us
    • Personal site
I already provided everything that is necessary. There is nothing else. All you need to do is put __longramfunc__ in front of the function. Compiler does the rest.
Alex
 

Offline Postal2

  • Frequent Contributor
  • **
  • Posts: 315
  • Country: ru
.... All you need to do is put __longramfunc__ in front of the function. ...
Yes, it's really simple. Then let's wait for "Hurray, it's working" from the author of the topic.
 

Offline Gabri74Topic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: it
Code: [Select]
__longramfunc__  void read_uid(uint32_t *uid)
{
  [OMISSIS]
}

On 32 bit platforms it must be __longramfunc__. More of the XC32 nonsense.

Hi ataradov, thanks a lot for the quick response, apologize for the late reply on my side.

This is the exact same code I wrote initially, but I got an error when using __longramfunc__ because it's not defined.
Grepping though all the code finally found that it's defined in xc32/v4.00/pic32c/include/newlib/sys/attribs.h
I then tried adding 'sys/attrib.h'  to the includes and also literally coping the __longramfunc__ definition into my code, but I get the exact same error as my first post:
Code: [Select]
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: Link Warning: attributes for input section '.RAMFUNC$.__stub' conflict with output section '.RAMFUNC$'
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .text.CLK_MainClockInitialize%449 LMA [004a264c,004a26df] overlaps section .text.sys_init%448 LMA [004a25b4,004a2657]
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: section .bss.resp.13237%53 VMA [20420e7c,20420f03] overlaps section .RAMFUNC$ VMA [20420dec,20420e8f]
Link Error: can't load section .RAMFUNC$ contents
/opt/microchip/xc32/v4.00/bin/bin/../../lib/gcc/pic32c/8.3.1/../../../../bin/bin/pic32c-ld: BFD (Microchip xc32 v4.00) 2.32.0.20190703 internal error, aborting at /data01/build/bamboo/xml-data/build-dir/M32DEV-BGT38-JOB1/src/gcc-8-merge/binutils/bfd/elf32-pic32c.c:324 in bfd_pic32_process_data_section

Could it be that I need to enable some buried option/flag in the project build options to solve this ?

Also I'm not using TCM/ITCM, could it be that not using those memories also (wrongly) disables some relocation linker behavior ?
 

Offline Gabri74Topic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: it
SOLVED! Thanks everyone for the help  :)

In the end was a missing option in the project compiler options.
I needed to enable 'Use indirect calls'  :palm:
Sorry, probably this was obvious for anyone but MPLAB is a relative new environment for me.
I'll attach a screenshot for the option for future reference.
Maybe a little more helping error message from the linker could have saved me some headache   ::)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf