cancel
Showing results for 
Search instead for 
Did you mean: 

We can't use "__attribute__((constructor))" for some init functions that run before main() at STM32L073RZ?

OXu.1
Associate

I've tried __attribute__((constructor)) on STM32F030R8T6 for running tests like Gtest framework by user-defined test. The code is shown as below:

 #define TEST(name)                                                    \
 	void Test##name(void);                                                  \
 	__attribute__((constructor))  void LoadTest##name(){                    \
 		RegisterTestFunction(Test##name);                                   \
 		g_Signal++;                                                         \
 	}                                                                       \
 														                    \
 	void Test##name(void)	                                                \
 
void  RegisterTestFunction(TestFunctionProto pTf)
{
	if(pTf == NULL)
	{
		return APPO_ERROR;
	}
	else if(StackGetSize(&g_TestFunctions) >= TEST_FUNCTIONS_MAX_NUM)
	{
		TestPrintf("Test Functions overflow!");
		return APPO_ERROR;
	}
	return StackPush(&g_TestFunctions, pTf);
}        
 
void RunAllTests(void)
{
	TestFunctionProto tmp = NULL;
	DebugPrintf("g_Signal = %d", g_Signal);
	while(FALSE == StackIsEmpty(&g_TestFunctions))
	{
		tmp = (TestFunctionProto) StackPop(&g_TestFunctions);
		tmp();
	}
}                              

Then I use TEST(***) to test my function like this:

TEST(Stack)
{  
 /*My test code*/
}

In the main() function , I run the "RunAllTests()", I could see the Test function results by UART printing :

But when I use the same code on the STM32L073RZ chip , I can't run my tests!

The LoadTest##name() function cannot run before main() even if I use "__attribute__((constructor))" !!!!:persevering_face:

Anybody can help me?

4 REPLIES 4
Pavel A.
Evangelist III

The startup code provided in the ST library is minimal and it does not run constructors.

You can add the needed code into the startup, or just call your tests from your main() as normal functions.

-- pa

No. It works for me (STMCubeIDE 1.4.1)

The usual newlib mechanism is used. See the sources: https://github.com/bminor/newlib/blob/master/newlib/libc/misc/init.c

For

__attribute__((constructor))  void LoadTest()
{
	__asm("nop");
}

the call stack is:

LoadTest() at main.c:61 0x8000224   

__libc_init_array() at 0x8001b6c   

Reset_Handler() at startup_stm32f042k6tx.s:119 0x800055e   

and, in a C++ project, for

class Klass {
public:
	Klass() {
		__asm("nop");
	}
};
 
Klass klass;

Klass::Klass() at maincpp.cpp:6 0x800037e   

__static_initialization_and_destruction_0() at maincpp.cpp:10 0x80003c0   

_GLOBAL__sub_I_klass() at maincpp.cpp:20 0x80003de   

__libc_init_array() at 0x8001b60   

Reset_Handler() at startup_stm32f042k6tx.s:119 0x8000552   

hth

KnarfB

Would have to be sure startup.s calls __libc_init_array

And that the linker script handled constructors

Not saying it doesn't work out-of-the-box these days, but they've shipped decades worth of broken code...

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

My bad ;( somehow in my projects call to __libc_init_array is removed.

In ST provided package for GCC toolchain it is in place and works.

-- pa