|
|
View previous topic :: View next topic |
Author |
Message |
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
Understanding how CCS stores strings. |
Posted: Tue Feb 25, 2020 9:10 am |
|
|
We recently stumbled into an issue where the code generator would use the wrong string for printf/sprintf, so I am trying to understand how strings are handled. There appears to be some limit where we add one more string, and then it uses the first string in the .lst file.
(i.e., printf("Value: %d", value); is the intent, but it outputs "xxxxxxx42" because it finds a string "xxxxxxxxxxxx". It's clearly using the correct one for the format string (since it puts the %d at the right spot) but it's outputting from a different string.)
I did a quick test showing printf of some constant strings, and declaring a few strings:
Code: | #include "main.h"
char *string1 = "A*A*A*A*";
char string2[] = "B*B*B*B*";
const char *string3 = "C*C*C*C*";
const char string4[] = "D*D*D*D*";
void main()
{
printf ("1111: %s\r\n", string1);
printf ("2222: %s\r\n", string2);
printf ("3333: %s\r\n", string3);
printf ("4444: %s\r\n", string4);
while(TRUE) // CCS compiler #define
{
//TODO: User Code
}
}
// End of main.c |
Constant strings like in the printf seem to store at the top, as does "const char string[]" using brackets, then all the rest are grouped after it.
Code: | const char string4[] = "D*D*D*D*";
00200: CLR 32
00202: MOV #20C,W3
00204: ADD W3,W0,W0
00206: TBLRDL.B[W0],W0L
00208: CLR.B 1
0020A: RETURN
0020C: DATA 44,2A,00
0020E: DATA 44,2A,00
00210: DATA 44,2A,00
00212: DATA 44,2A,00
00214: DATA 00,00,00
printf ("1111: %s\r\n", string1);
00216: CLR 32
00218: MOV #222,W3
0021A: ADD W3,W0,W0
0021C: TBLRDL.B[W0],W0L
0021E: CLR.B 1
00220: RETURN
00222: DATA 31,31,00
00224: DATA 31,31,00
00226: DATA 3A,20,00
00228: DATA 25,73,00
0022A: DATA 0D,0A,00
0022C: DATA 00,00,00
printf ("2222: %s\r\n", string2);
0022E: CLR 32
00230: MOV #23A,W3
00232: ADD W3,W0,W0
00234: TBLRDL.B[W0],W0L
00236: CLR.B 1
00238: RETURN
0023A: DATA 32,32,00
0023C: DATA 32,32,00
0023E: DATA 3A,20,00
00240: DATA 25,73,00
00242: DATA 0D,0A,00
00244: DATA 00,00,00
printf ("3333: %s\r\n", string3);
00246: CLR 32
00248: MOV #252,W3
0024A: ADD W3,W0,W0
0024C: TBLRDL.B[W0],W0L
0024E: CLR.B 1
00250: RETURN
00252: DATA 33,33,00
00254: DATA 33,33,00
00256: DATA 3A,20,00
00258: DATA 25,73,00
0025A: DATA 0D,0A,00
0025C: DATA 00,00,00
printf ("4444: %s\r\n", string4);
0025E: CLR 32
00260: MOV #26A,W3
00262: ADD W3,W0,W0
00264: TBLRDL.B[W0],W0L
00266: CLR.B 1
00268: RETURN
0026A: DATA 34,34,00
0026C: DATA 34,34,00
0026E: DATA 3A,20,00
00270: DATA 25,73,00
00272: DATA 0D,0A,00
00274: DATA 00,00,00
. . . snip . . .
.................... // End of main.h
....................
....................
char *string1 = "A*A*A*A*";
*
002C2: MOV #2A41,W4
002C4: MOV W4,802
002C6: MOV #2A41,W4
002C8: MOV W4,804
002CA: MOV #2A41,W4
002CC: MOV W4,806
002CE: MOV #2A41,W4
002D0: MOV W4,808
002D2: CLR.B 80A
002D4: MOV #802,W4
002D6: MOV W4,800
....................
char string2[] = "B*B*B*B*";
002D8: MOV #2A42,W4
002DA: MOV W4,80C
002DC: MOV #2A42,W4
002DE: MOV W4,80E
002E0: MOV #2A42,W4
002E2: MOV W4,810
002E4: MOV #2A42,W4
002E6: MOV W4,812
002E8: CLR.B 814
.................... char *string1 = "A*A*A*A*";
.................... char string2[] = "B*B*B*B*";
const char *string3 = "C*C*C*C*";
002EA: MOV #2A43,W4
002EC: MOV W4,816
002EE: MOV #2A43,W4
002F0: MOV W4,818
002F2: MOV #2A43,W4
002F4: MOV W4,81A
002F6: MOV #2A43,W4
002F8: MOV W4,81C
002FA: CLR.B 81E
....................
.................... const char *string3 = "C*C*C*C*";
.................... const char string4[] = "D*D*D*D*";
....................
.................... void main()
|
Has anyone looked into how the strings work that might shed some light on this? I am trying to create a short one-file test case (if possible; may be a Multi-Unit bug) to send to CCS.
Thanks. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Tue Feb 25, 2020 9:23 am |
|
|
I think it must be a multi-unit bug, since I have stuff with tens of KB of strings
and have never seen a problem. But I don't use MCU's.
There are some 'bodges' that appear at particular points in the ROM space
I asked before about whether you were using PSV. If you are not, consider it.
With PSV, the ROM space used for this data is mapped into a window in the
RAM address map, and the functions using const strings can treat them as
normal RAM strings. Makes access faster, and is likely to avoid such problems. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Tue Feb 25, 2020 9:52 am |
|
|
I see on startup that our strings are being copied into RAM. The code at the start of each block is being called in a huge series of CALL statements during program init. This explains why we are so low on memory ;-)
I am looking at the source where the printf is, trying to figure out how it is getting the wrong string. I think I can show that to CCS and they may understand what is going on. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Tue Feb 25, 2020 1:27 pm |
|
|
Are you running in ANSI mode?.
If you do, this makes a 'const', a RAM variable that cannot normally be
changed. Result you use RAM for every single one. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Tue Feb 25, 2020 1:43 pm |
|
|
Ttelmah wrote: | Are you running in ANSI mode?.
If you do, this makes a 'const', a RAM variable that cannot normally be
changed. Result you use RAM for every single one. |
I didn't know there was an ANSI mode. These are just "make a new project with the wizard and use its defaults", then I add things like #case and stuff to enable printf. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Feb 25, 2020 7:01 pm |
|
|
ANSI is in the manual, and it's important to understand what it changes.
Also
stop using the 'wizard'. Sooner AND later, it'll trip you up ! Some other 'programmer', programmed the 'wizard' with HIS defaults NOT yours. So eventually your program that 'should work'.... doesn't.
I don't use it, debuggers or simulators. None can be 100% trusted. |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Feb 26, 2020 1:36 pm |
|
|
temtronic wrote: | ANSI is in the manual, and it's important to understand what it changes. |
Thanks. I didn't find anything int he online manual/help in the IDE, but I see this in the PDF:
Quote: | ANSI
Default data type is SIGNED all other modes default is UNSIGNED.
Compilation is case sensitive, all other modes are case insensitive.
Pointer size is set to *=16 if the part has RAM over 0FF. |
Hmm. Does this mean an "int" is unsigned in default? Not much detail, though -- #case and signed. Does it do more? _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Feb 26, 2020 1:57 pm |
|
|
temtronic wrote: | ANSI is in the manual, and it's important to understand what it changes. |
Wow. Huge difference in code generation from the default.
With #device ANSI:
Code: | ROM used: 41274 bytes (24%)
Largest free fragment is 43520
RAM used: 13080 (80%) at main() level
15179 (93%) worst case
Stack used: 94 loc |
Without (CCS4 default):
Code: | ROM used: 37486 bytes (21%)
Largest free fragment is 43520
RAM used: 6533 (40%) at main() level
8635 (53%) worst case
Stack used: 94 locations (54 in main + 40 for interrupts)
Stack size: 128 |
_________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 552 Location: Des Moines, Iowa, USA
|
|
Posted: Thu Jun 23, 2022 11:48 am |
|
|
Our new projects have made done using one C file and #includes, but our legacy projects are all multi-unit compile. I'm back to trying to figure this out, waiting to see what CCS says.
It will be wanting to print a 6-character string ("set.\r\n") but points to the location of a completely different string. Fun
I have at least caught the compiler pointing to the wrong constant ROM data:
Code: |
.............................. DEBUG_PRINTF ("1 sweepComplete FALSE\r\n");
01CD4 200001 MOV #0,W1 : W1 = 0
01CD6 780001 MOV W1,W0 : W0 = W1
01CD8 EF6001 CLR.B 1 : W0H = 0
*** HERE:
01CDA 0208DE 000000 CALL 8DE :
01CDE E80081 INC W1,W1 : W1 = W1 + 1
01CE0 781F81 MOV W1,[W15++] : Push W1 to TOS
01CE2 F86518 PUSH 6518 : PUSH [6518] to TOS
01CE4 9FFFE0 MOV.B W0L,[W15-#2] : [W15+-2] = W0L
01CE6 F96518 POP 6518 : POP TOS to [6518]
01CE8 0211F0 000000 CALL 11F0 :
01CEC 7800CF MOV [--W15],W1 : POP TOS to [--W15]
01CEE 200160 MOV #16,W0 : W0 = 16
01CF0 E60810 CPSGT W1,W0 : Skip if W1 > W0
01CF2 37FFF1 BRA 1CD6 : GoTo 1CD6
Elsewhere...
.............................. DEBUG_PRINTF ("set.\r\n");
06260 200001 MOV #0,W1 : W1 = 0
06262 780001 MOV W1,W0 : W0 = W1
06264 EF6001 CLR.B 1 : W0H = 0
*** HERE:
06266 0208DE 000000 CALL 8DE :
0626A E80081 INC W1,W1 : W1 = W1 + 1
0626C 781F81 MOV W1,[W15++] : Push W1 to TOS
0626E F808C2 PUSH 8C2 : PUSH [8C2] to TOS
06270 A9E8C3 BCLR.B 8C3.7 : [8C3.7] = 0
06272 F86518 PUSH 6518 : PUSH [6518] to TOS
06274 9FFFE0 MOV.B W0L,[W15-#2] : [W15+-2] = W0L
06276 F96518 POP 6518 : POP TOS to [6518]
06278 0211F0 000000 CALL 11F0 :
0627C F908C2 POP 8C2 : POP TOS to [8C2]
0627E 7800CF MOV [--W15],W1 : POP TOS to [--W15]
06280 200050 MOV #5,W0 : W0 = 5
06282 E60810 CPSGT W1,W0 : Skip if W1 > W0
06284 37FFEE BRA 6262 : GoTo 6262
...and...
.............................. DEBUG_PRINTF ("set.\r\n");
062EE 200001 MOV #0,W1 : W1 = 0
062F0 780001 MOV W1,W0 : W0 = W1
062F2 EF6001 CLR.B 1 : W0H = 0
*** HERE:
062F4 0208DE 000000 CALL 8DE :
062F8 E80081 INC W1,W1 : W1 = W1 + 1
062FA 781F81 MOV W1,[W15++] : Push W1 to TOS
062FC F808C2 PUSH 8C2 : PUSH [8C2] to TOS
062FE A9E8C3 BCLR.B 8C3.7 : [8C3.7] = 0
06300 F86518 PUSH 6518 : PUSH [6518] to TOS
06302 9FFFE0 MOV.B W0L,[W15-#2] : [W15+-2] = W0L
06304 F96518 POP 6518 : POP TOS to [6518]
06306 0211F0 000000 CALL 11F0 :
0630A F908C2 POP 8C2 : POP TOS to [8C2]
0630C 7800CF MOV [--W15],W1 : POP TOS to [--W15]
0630E 200050 MOV #5,W0 : W0 = 5
06310 E60810 CPSGT W1,W0 : Skip if W1 > W0
06312 37FFEE BRA 62F0 : GoTo 62F0 |
If I am allowed to make the change, I may try to get the project building using the one-C, #include method and see what that does.
Fun fun. _________________ Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|