[quote user="Chester Gillon"]b) In cases 3 and 5 it seems their might be a GCC compiler bug whereby the use of __attribute__ ((persistent)) on variable which otherwise would be placed in the .bss segment gets ignored.[/quote]When the -save-temps option was used to inspect the generated assembler, in cases 3 and 5 the count variable was handled as a common symbol as indicated by .comm for test case 3: .local count .comm count,1,1 And test case 5 : .local count.3248 .comm count.3248,1,1 Looking at the source code for msp430-gcc-5.3.0.224, in the msp430_data_attr() function in msp430-gcc-5.3.0.224_source-full\gcc\gcc\config\msp430\msp430.c there is the following block: /* If this var is thought to be common, then change this. Common variables are assigned to sections before the backend has a chance to process them. */ if (DECL_COMMON (* node)) DECL_COMMON (* node) = 0; What might be happening is that common variables bypass the logic in the msp430_select_section() function which checks for the presence of the persistent attribute to select the data section to be used, although I haven't attempted to study the msp430-gcc-5.3.0.224 source code in detail to prove this. As an alternative, changed the test cases to use __attribute__ ((section (".persistent"))), instead of __attribute__ ((persistent)), to directly specify the .persistent section to be used for persistent variables. 1) Attempting to use __attribute__ ((section (".persistent"))) on a variable with automatic storage: #include #include #include int main(void) { __attribute__ ((section (".persistent"))) uint8_t count = 0; WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer count++; printf("The count:%u\n", count); return 0; } The result is that the compiler reports an error due to attempting to set the data section for a variable with automatic storage: ../main.c: In function 'main': ../main.c:7:55: error: section attribute cannot be specified for local variables __attribute__ ((section (".persistent"))) uint8_t count = 0; i.e. the compiler now traps an invalid attempt to make a variable with automatic storage persistent. 2) Attempting to use __attribute__ ((section (".persistent"))) on a global variable initialized to zero: #include #include #include __attribute__ ((section (".persistent"))) uint8_t count = 0; int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer count++; printf("The count:%u\n", count); return 0; } The result is that the count variable is persistent, in that count is set to zero when the program is downloaded and count then retains its value across a Hard Reset. 3) Attempting to use __attribute__ ((section (".persistent"))) on a file static global variable initialized to zero: #include #include #include static __attribute__ ((section (".persistent"))) uint8_t count = 0; int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer count++; printf("The count:%u\n", count); return 0; } The result is that the count variable is persistent, in that count is set to zero when the program is downloaded and count then retains its value across a Hard Reset. 4) Attempting to use __attribute__ ((section (".persistent"))) on a file static global variable initialized to one: #include #include #include static __attribute__ ((section (".persistent"))) uint8_t count = 1; int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer count++; printf("The count:%u\n", count); return 0; } The result is that the count variable is persistent, in that count is set to one when the program is downloaded and count then retains its value across a Hard Reset. 5) Attempting to use __attribute__ ((section (".persistent"))) on a function static variable initialized to zero: #include #include #include int main(void) { static __attribute__ ((section (".persistent"))) uint8_t count = 0; WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer count++; printf("The count:%u\n", count); return 0; } The result is that the count variable is persistent, in that count is set to zero when the program is downloaded and count then retains its value across a Hard Reset. 6) Attempting to use __attribute__ ((section (".persistent"))) on a function static variable initialized to one: #include #include #include int main(void) { static __attribute__ ((section (".persistent"))) uint8_t count = 1; WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer count++; printf("The count:%u\n", count); return 0; } The result is that the count variable is persistent, in that count is set to one when the program is downloaded and count then retains its value across a Hard Reset. The conclusion is that __attribute__ ((section (".persistent"))) is a more reliable way to make a variable persistent, as opposed to using __attribute__ ((persistent)).
↧