This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello!
I'm working on program for custom version of MSP430F149 chip and face following problem:
There is peripheral device (read FIFO) mapped to 0x104, 0x106 addresses. GCC compile only first access to it and optimize out all others.
I tried next:
[VERSION_0]
func.h:
uint8_t read_fifo (uint16_t *d_l, uint16_t *d_h);
func.c:
extern volatile uint16_t RFIFO_L; extern volatile uint16_t RFIFO_H; uint8_t read_fifo (uint16_t *d_l, uint16_t *d_h) { *d_l = RFIFO_L; *d_h = RFIFO_H; return 0; }
main.c:
#include "func.h" int main () { // Stop the watchdog WDTCTL = WDTPW + WDTHOLD; uint16_t d[2]; while (1) { read_fifo(d, d + 1); if (d[0] == some_value0 && d[1] == another_value0) { // some processing } else if (d[0] == some_value1 && d[1] == another_value1) { // another processing processing } } }
/some/path/ti/msp430-gcc/include/msp430f149_symbols.ld:
// added two lines
PROVIDE(RFIFO_L = 0x0104);
PROVIDE(RFIFO_H = 0x0106);
RESULT: there is only first read access to FIFO, which returns zero as expectable, but no any other access (I expected that it will read fifo untill power off).
[VERSION_1]
remove extern volatile declarations from func.c and add to /some/path/ti/msp430-gcc/include/msp430f149.h two lines:
sfr_w(RFIFO_L); sfr_w(RFIFO_H);
RESULT: the same
[VERSION_2]
modify SFR entry length in /some/path/ti/msp430-gcc/include/msp430f149.ld to 0x110 address:
SFR : ORIGIN = 0x0000, LENGTH = 0x0110
RESULT: the same
[VERSION_3]
restore msp430f149_symbols.ld, msp430f149.ld and msp430f149.h, in func.c added defines instead of extern volatile:
#define RFIFO_L (*(volatile uint16_t *)(0x0104)) #define RFIFO_H (*(volatile uint16_t *)(0x0106))
RESULT: the same
What I did wrong and how to tell MSPGCC not optimize access to these volatile variables?
Compilation command:
/some/path/ti/msp430-gcc/bin/msp430-elf-gcc -I/some/path/ti/msp430-gcc/include -mmcu=MSP430F149 -Wall -O0 -msmall -flto -fwrapv -mtiny-printf -I./ -L/some/path/ti/msp430-gcc/include -Wl,-Map,test.map,--gc-sections,--just-symbols,msp430f149_symbols.ld,--oformat=ihex main.c func.c -o MSP430F149.a43
GCC version output:
gcc version 9.2.0 (Mitto Systems Limited - msp430-gcc 9.2.0.50)
Configured with: ../../gcc/configure --target=msp430-elf --enable-languages=c,c++ --disable-nls --enable-initfini-array --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --enable-target-optspace --enable-newlib-nano-formatted-io --with-pkgversion='Mitto Systems Limited - msp430-gcc 9.2.0.50'
Thread model: single
I think that the problem here isn't the locations declared as volatile but that access is via a function which results in that volatile specification being lost. Even if you added "volatile" to the declaration of the intermediate array d[], it wouldn't help.
Hmm, ok, I moved code with that volatiles vars into main function and it's been work until I switched optimization flag from -O0 to -Os. With -Os behaviour the same - first acces ok, all following optimized out.
Also I think that restriction of using global volatile variables only in main function is weird and it looks like GCC bug.
David Schultz36 said:I think that the problem here isn't the locations declared as volatile but that access is via a function which results in that volatile specification being lost. Even if you added "volatile" to the declaration of the intermediate array d[], it wouldn't help.
What does the assembly code (--save-temps) look like? I don't see this behavior with v7.3.2.154 (Mitto), at least judging by the assembly code. (I don't have an F149.)
read_fifo() is required to read from R_FIFO_x because of volatile, but it's required to write to *d_X because they're pointers (in most cases the optimizer must assume that an assignment through a pointer stores "anywhere and everywhere"). Or is main just not calling read_fifo() at all?
Thank you very much for -save-temps option, that the one I really need. After inspecting assembler code I found out that problem not in volatile accesses. It's delay function:
inline void delayNtick (uint32_t nticks) { volatile unsigned long i = nticks; while (i--); }
which've been compiled into that:
; start of prologue SUB.W #4, R1 ; end of prologue MOV.W #0, @R1 MOV.W #0, 2(R1) .L2: MOV.W @R1, R12 MOV.W 2(R1), R13 MOV.W R12, R14 ADD #-1, R14 ; cy MOV.W R13, R15 ADDC #-1, R15 MOV.W R14, @R1 MOV.W R15, 2(R1) BIS.W R13, R12 CMP.W #0, R12 { JNE .L2 ; start of epilogue ADD.W #4, R1 RET
So calling delayNtick(0) for minimal latency, will result in maximum latency. Rewriting delay function to while (i) --i; fixed the problem.
Bruce McKenney47378 said:What does the assembly code (--save-temps) look like? I don't see this behavior with v7.3.2.154 (Mitto), at least judging by the assembly code. (I don't have an F149.)
read_fifo() is required to read from R_FIFO_x because of volatile, but it's required to write to *d_X because they're pointers (in most cases the optimizer must assume that an assignment through a pointer stores "anywhere and everywhere"). Or is main just not calling read_fifo() at all?
**Attention** This is a public forum