noinit section getting cleared by _do _clear_bss

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have been trying to figure out why my .noinit data is getting cleared on startup, but not having any luck. I have a tiny416 and mega4809, both show the same problem.

 

The following is a minimal piece of code to demonstrate my problem-

//attiny416, mplabx 5.15, xc8 2.05, gcc 5.4.0
//turn off ld garbage collection of unused sections for this test
//======================
// .noinit test
//======================
char data_var = 4;
char bss_var;
char noinit_var __attribute(( section(".noinit") ));
int main(void) {
    for(;;){}
}

/*
result
======================
00803f01 g     O .noinit 00000001 noinit_var
00803f02 g     O .data   00000001 data_var
00803f00 g     O .bss    00000001 bss_var

00000034 <.dinit>: //my comments added
  34:   3f 02   0x3f02 - start of data
  36:   3f 03   0x3f03 - end of data
  38:   00 00   0x00 = do load data
  3a:   a2 3f   from flash starting at 0x00a2
  3c:   01 3f   0x3f01 - start of .noinit
  3e:   02 80   0x3f02 - end of .noinit, 0x80 = do clear bss
  40:   3f 00   0x3f00 - start of bss
  42:   3f 01   0x3f01 - end of bss
  44:   80 00   0x80 = do clear bss

*/

the data init code from libgcc uses the .dinit data shown above to run through sections of data/bss- either initializing data from flash or clearing ram (bss). The clearing of bss is indicated by a starting and ending address followed by 0x80 (bit 7 set). Initialized data has a starting and ending address, a 0x00 (bit 7 clear) and a starting flash address.

 

Why the .noinit section address is showing up in .dinit, I guess is the question. Maybe I'm doing something obviously wrong, or its a known problem, or ? I downloaded gcc/binutils source code for these versions (I think), but that's always an exercise in trying to read obfuscated code and usually I am left wondering why it works at all. I grep a bunch, but there is not much to be found for '.noinit', and nothing to be found for '.dinit' (something/somewhere is producing that section). I'm not even sure I'm looking at the right libgcc source code as it doesn't really match up with what I'm seeing for init code (mine loads values from .dinit, and it looks like libgcc source I'm looking at uses hard coded values).

 

This is what the produced .s file looks like (--save-temps)-

	.file	"newmain.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__CCP__ = 0x34
__tmp_reg__ = 0
__zero_reg__ = 1
	.section	.text.startup.main,code
.global	main
	.type	main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
.L2:
	rjmp .L2
	.size	main, .-main
.global	noinit_var
	.section	.noinit,bss
	.type	noinit_var, @object
	.size	noinit_var, 1
noinit_var:
	.zero	1
	.comm	bss_var,1,1
.global	data_var
	.section	.data.data_var,data
	.type	data_var, @object
	.size	data_var, 1
data_var:
	.byte	4
	.ident	"GCC: (AVR_8_bit_GNU_Toolchain_3.6.2_122) 5.4.0"
.global __do_copy_data
.global __do_clear_bss

that noinit_var section doesn't look right (shouldn't  @progbits be specified or something?)

 

Any suggestions? I can come up with various ways to get equivalent of noinit data, but just want to find out why .noinit section is not working in my case.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, this is what you use-

 

__attribute__((persistent))

 

I made the mistake of thinking getting the gcc source code would help. I already had the xc8 2.05 source code, but sort of forgot I already had it for some reason. It helps to have the actual version being used (quite different from official gcc). Looking through libgcc (lib1funcs.S), I can now see the startup code matches what I have and is using _dinit labels, I can also see binutils is doing nothing with .noinit but there are a lot of references to persist/persistent. I can also see the .dinit section is created by the linker. The solution finally hit me as I have been through something similar for the pic32 (not that long ago- my memory must be failing)- I had a simple test app for my pic32mm for peristent (noinit) data which I had used the 'persistent' attribute. So I tried that for the avr and it works. So it seems the new trend is to get a 'persistent' attribute into the linker code to take care of what previously was done with an actual named section.

 

If I was good at this, it wouldn't have taken me a day and a half to figure out.

 

Maybe this will help someone else also. Maybe not. Maybe no one here uses xc8.

Last Edited: Mon. Jul 1, 2019 - 12:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

noinit_var should be in .section .noinit,"aw",@nobits
.
and this is what avr-gcc v5 (FSF) generates. I never saw that .dinit stuff, libgcc (FSF) uses symbols defined in the linker script. GCC doku lists persistent only for MSP430, it does similar but different things like .noinit.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

toward the bottom, under source archives-

https://www.microchip.com/development-tools/pic-and-dspic-downloads-archive

 

Yes, it is quite different than what you are using and it appears this is where all the recent work is being done from the mchp side of things. So documentation for things like 'persistent' do not exist, but that's what it is for this version (xc8-avr). If you don't use xc8-avr, then keep on doing what you were doing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just wonder what's the benefit of all of it, because the original feature is working perfectly fine and is well established.
.
The directive for data_var is still odd and looks broken.
.
FYI, output is done by gcc/varasm.c and target hooks in gcc/config/avr/avr.c. There should be no need for special handling of .noinit in gcc, as or ld; all that's needed is correct placement of .noinit in the linker script.
.
GCC v5 was released back in 2015, current is v9, and so I wonder why they are retro-fitting broken stuff without any test coverage: even if features are added they should not break existing ones.

avrfreaks does not support Opera. Profile inactive.

Last Edited: Fri. Jul 5, 2019 - 09:56 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>I just wonder what's the benefit of all of it, because the original feature is working perfectly fine and is well established.

 

They have been using the persistent attribute in xc16/32 for some time (and __persistent in xc8-pic), so I'm guessing they want to make xc8-avr the same. I was wrong earlier, they do list this attribute in the xc8-avr user manual, but they also list the attribute as __persistent (should be plain persistent when used as an attribute). It does get a little confusing as when you search for something on the internet, you may end up looking at avr info that no longer applies. So I guess if using xc8-avr, consult the manual first, and in this case would have pointed be in the right direction even though the syntax was wrong.

 

>and so I wonder why

 

That's the way they work. The xc16/32 compilers are old, they make all their changes in them but they never work their way back to gcc. Xc8-avr will become the same, you will end up with two versions- the one from mchp and the gcc version.