/* This stuff is copied from FLASH to RAM by C code in the main stub */
.all_nonboot_data :
{
. = ALIGN(4);
_s_nonboot_data = .; /* create a global symbol at data start */
*(.data .data*) /* .data sections */
. = ALIGN(4);
_e_nonboot_data = .; /* define a global symbol at data end */
} >RAM AT >FLASH_APP
/* used by the main stub C code to initialize data */
_si_nonboot_data = LOADADDR(.all_nonboot_data);
/* Uninitialized data section for rest of xxx */
/* This stuff is zeroed by C code in the main stub */
. = ALIGN(4);
.all_nonboot_bss :
{
_s_nonboot_bss = .; /* define a global symbol at bss start */
*(.bss .bss* .COMMON .common .common*)
. = ALIGN(4);
_e_nonboot_bss = .; /* define a global symbol at bss end */
} >RAM
// Entry point for code called by the boot block - has to be located at the base of FLASH+32k
// This is done in linkfile
// Has to be "int" otherwise compiler complains :)
// Various measures to prevent it getting optimised away, which probably don't work. What does work
// is vector2 (which is in assembler and thus immune to optimisation) having a dword pointing to main().
__attribute__((optimize("O0")))
__attribute__((used))
int main()
{
// Initialise DATA
extern char _s_nonboot_data;
extern char _e_nonboot_data;
extern char _si_nonboot_data;
void * memcpy (void *__restrict, const void *__restrict, size_t);
memcpy(&_s_nonboot_data, &_si_nonboot_data, &_e_nonboot_data - &_s_nonboot_data);
// Zero BSS and COMMON
extern char _s_nonboot_bss;
extern char _e_nonboot_bss;
void * memset (void *, int, size_t);
memset(&_s_nonboot_bss, 0, &_e_nonboot_bss - &_s_nonboot_bss);
// Go to user program
main_real();
// We should never get here
for (;;);
}
// Vectab2.s ends up linked here, at base of FLASH + 32k + 512
Hence I wondered what section an initialised struct (a local one, thus on the function stack) is supposed to be in, but the answer must be None. It cannot possibly be anything like that, because the function would not be thread-safe.
4 An object whose identifier is declared with no linkage and without the storage-class
specifier static has automatic storage duration.
5 For such an object that does not have a variable length array type, its lifetime extends
from entry into the block with which it is associated until execution of that block ends in
any way. (Entering an enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively, a new instance of the
object is created each time. The initial value of the object is indeterminate. If an
initialization is specified for the object, it is performed each time the declaration is
reached in the execution of the block; otherwise, the value becomes indeterminate each
time the declaration is reached.
I don't know and I don't want to know what's "thread safe".
sprintf(datetime, "%c%c%c %02d%02d20%02d %02d%02d%02d DOY=%03d",
Does anyone know if it is even possible to use an STLINK debugger to load code linked to run at 0x8008000 (instead of 0x8000000) and it programs the right cpu flash addresses? IOW, does not try program anything into 0x8000000-0x8007fff).
void xxx_get_date_time(char *datetime)
{
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
int i = (sDate.WeekDay - 1) * 3;
sprintf(datetime, "%c%c%c %02d%02d20%02d %02d%02d%02d DOY=%03d",
d_o_w[i],d_o_w[i+1],d_o_w[i+2],sDate.Date, sDate.Month, sDate.Year,
sTime.Hours, sTime.Minutes, sTime.Seconds, day_of_year(sDate.Date, sDate.Month-1, sDate.Year+100));
}
080582ee: str r6, [sp, #12]
080582f0: str r5, [sp, #8]
080582f2: str r4, [sp, #4]
080582f4: str.w r8, [sp]
080582f8: ldr r3, [sp, #32]
080582fa: mov r2, r7
080582fc: ldr r1, [pc, #20] ; (0x8058314 <xxx_get_date_time+168>)
080582fe: ldr r0, [sp, #36] ; 0x24
08058300: bl 0x8048a50 <sprintf_>
.rodata.str1.4
0x000000000807157c 0x2c8 ../LIBxxx\libxxx.a(xxx_NTP.o)
0x2f0 (size before relaxing)
.rodata.str1.4
0x0000000008071844 0x58 ../LIBxxx\libxxx.a(xxx_rtc.o)
.rodata.str1.4
0x000000000807189c 0x1a ../LIBxxx\libxxx.a(xxx_sensors.o)
*fill* 0x00000000080718b6 0x2
sprintf(datetime, "%c%c%c %02d%02d20%02d %02d%02d%02d DOY=%03d",
/* This collects all other stuff, which gets loaded into FLASH after xxx_main.o above */
.code_constants_etc :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_e_code_constants_etc = .; /* define a global symbol at end of code */
} >FLASH_APP
/**
* @brief UART MSP Init.
* @param huart pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval None
*/
__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(huart);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_MspInit could be implemented in the user file
*/
}
I think it should be noted that the --whole-archive option also adds all the symbols within the given libraries, which will solve this problem but will increase the size of the executable and may produce additional linking errors.
Some of this is easy to take care of but the ST code is full of "software purist" kind of total crap like this
...
Why do people write this shit? You spend so much time typing up empty functions with __weak on the front.
One approach is to not use libraries at all.
I did some googling and the answer here appears to have a solution
Do you intend to supply your version of CubeF4 (= the "library"), and resolve conflicts stemming from users wishing to use another version of that "library"?
For example, if you need TLS, use a library. If you need UART on MCU, do not.
People write confusing bullshit boilerplate so that
A) they can be replaced by ChatGPT
B) those who got replaced can complain how ChatGPT took their jobs
C) those who replaced them can boast how excellent ChatGPT is as it can write human-level code.
Is there a tool which one can run on a whole project and which can report which functions are __weak but are actually being called by real code?
The other sources for this project are mostly the ST ports of LWIP, FreeRTOS, etc. These do all work and have been well tested.
The difference is this:
if (prng() == 42) foo();
Is foo() called or not?
QuoteThe difference is this:
if (prng() == 42) foo();
Is foo() called or not?
What I had in mind is purely static analysis.
For example there is clearly a "decision point" during the link process where a __weak function is not overriden by a symbol which originates from a library, whereas it would be overriden by a symbol which originates from a .o file.
So the linker could in principle generate such a report.
ST have generated __weak functions all over the place.
1) The stuff has been around a very long time, and been in fairly active development for years of that time.
2) The product has been in development for years and a number of boards have been running 24/7, running a fully loaded product.
It's easy to write "weak safety" but do you want to work for me for a few years for free? Too many one-liners.