I have the following structure:
struct fence_struct { unsigned char mode; char sitename[13]; unsigned char sector_nr; unsigned char sector_tot; unsigned int start; unsigned int feeder_offset; unsigned int len; unsigned int line_len; unsigned char begin_far; unsigned int res_norm; unsigned int res_min; unsigned int res_max; unsigned char wire_amount; unsigned char wire_name[12]; }; xdata struct fence_struct fence;
strcpy(fence.sitename, "SITENAME");
;strcpy(fence.sitename, "SITENAME"); ;SOURCE LINE # 1535 MOV R0,#LOW (fence+01H) MOV R4,#HIGH (fence+01H) MOV R5,A MOV R3,#0FFH MOV R2,#HIGH (?SC_403) MOV R1,#LOW (?SC_403) LCALL ?C?STRCPY
;strcpy(fence.sitename, "SITENAME"); ;SOURCE LINE # 4306 MOV R0,#LOW (fence+01H) MOV R4,#HIGH (fence+01H) MOV R5,#01H MOV R3,#0FFH MOV R2,#HIGH (?SC_403) MOV R1,#LOW (?SC_403) LCALL ?C?STRCPY
What you found is not a bug. If it were, you should have demonstrated incorrect behaviour of the generated code. The bug, if any, is in your expectations. Note that the only actual difference between you two assembly outputs is
MOV R5,A
MOV R5,#01H
Your explanation sounds good, but it doesn't explain why the 1st call doesn't initialise the string correctly and the 2nd one does. Also, as a further test I've added the lines
fence.sitename[0] = '1'; fence.sitename[1] = '\0';
"The bug, if any, is in your expectations." Hans-Bernhard, I think he expected the code to work which seems pretty reasonable. Johann, which version of the compiler and linker are you using, and which optimisation settings have you selected? Stefan
what about:
strcpy( &fence.sitename, "SITENAME");
or perhaps:
strcpy( &fence.sitename[0], "SITENAME" );
I'm using C51 ver 7.01, linker ver 5.01 and optimisation level 8 - set to favour size.
I found my problem - if you can call it a problem! I use a Dallas DS5000T MCU and if I switch the whole thing off by the power and on again (as opposed to just taking it out of Pgm mode) the 1st call also initialises correctly. I cannot explain why the DS5000T works correctly only after it is switched off and on, but it solved my problem. Thanks for everyones help.
The following is incorrect: strcpy( &fence.sitename, "SITENAME" ); The following is correct: strcpy( &fence.sitename[0], "SITENAME" ); but achieves exactly the same as: strcpy( fence.sitename, "SITENAME" ); Stefan
[Disclaimer: I've never used or seen a DS5000T] You still haven't even begun to describe what the "incorrect initialization" actually behaves like. Are you sure "going out of Pgm mode" even calls the initialization #1, and with the proper arguments/register contents, too? This is one of many questions left open to speculation by the very incomplete example case you showed.
The DS5000T uses NVRAM with a on-board lithium cell. It also has a built-in boot loader. You place it in Program mode by taking the RST pin high and the PSEN pin low simultaneously. Pgm mode is ended when "power is removed from the device or when the Program Load configuration strapping (RST=1, PSEN=0) is removed". "If the Program Load configuration strapping is removed with power still applied at Vcc, the device will undergo an internal hardware reset and will begin executing code from the reset vector location at 0000H in Program Memory." --> So you see an exit from pgm mode is supposed to behave the same as a power-up. Therefore I cannot explain why the 1st call only executes properly with a power-up. I know initialization #1 gets executed because all the other lines of that function gets executes and there's no branches. When I say "incorrect initialization" it means a bunch of garbage is displayed on the LCD when I printf() the string. Also it prints over other text which indicates the string is not terminated with a NULL. I hope this answers you questions.
Is it possible that your program changes the MCON register in a way that affects the partition address. And, after you exit program mode, the first time the program runs, the partition address is changed. Then, after a cold start, since the partition address is set correctly, everything works OK? Since you are using a DS5000, your XDATA starts at the partition address. Have you specified it that way to the linker? Jon
I've checked that I don't write to the MCON register anywhere in my code. I only write to it after the hex file has been loaded into pgm mem while the MCU is still in Pgm mode. Yes, I specify in Keil that the Code mem is from 0x0000-0x6FFF and the Xdata mem is from 0x7000-0x7FFF. I've also noticed that a second reset (after the 1st which took it out of pgm mode) has the same effect as a cold start.
OK, so the state of this analysis is that probably the content of the Accu is not the expected 01H if your routine number 1 is called as the consequence of a "going out of PGM mode" condition. Among other things, this just might be a hardware bug. Without seeing a lot more of your code (or a smaller, self-contained example case that still shows the problem), it'll be quite impossible for anyone but yourself to debug this further. You may have to use an ICE or logic analyser to see what the CPU actually does. (BTW: does it work in the Keil simulator?)
Well, If the program works after a cold start, I seriously doubt that there is a compiler or code generation problem. In fact, I'd start looking at the state of the device after exiting programming mode. However, since your device PROBABLY won't be programmed (in the field) and immediately started running (in the field) I don't think this is a critical issue. I mean, you are going to load the program into the device and send it somewhere (probably unpowered). Once it gets to its destination and powered-up, everything will work fine (since cold starts work OK). Jon
I agree with you: The fact that it initialises the variables correctly after a cold start or after the 2nd reset shows to me that, contrary to what the datasheet says, the DS5000T DOES NOT execute a complete reset after it's taken out of pgm mode. But then again, why does it initialise the numerical variables before and after the strcpy() in question correctly but not the strcpy() itself??