Hallo zusammen. Ich nutze IAR Embeddet Workbench IDE V.5.20 und den µC MSP430F2013. Ich bekomme folgenden Error: Error[e104]: Failed to fit all segments into specified ranges. Problem discovered in segment CODE. Unable to place 25 block(s) (0x7bc byte(s) total) in 0x7b6 byte(s) of memory. The problem occurred while processing the Heißt das mit anderen Worten, dass der µC stack voll ist? Das wäre sehr krass, weil so viel Code habe ich noch gar nicht geschrieben. Vielen Dank alle Hilfe. :) BL
BL schrieb: > Heißt das mit anderen Worten, dass der µC stack voll ist? Nein, schlimmer: der Programmspeicher ist voll. > weil so viel Code habe ich noch gar nicht geschrieben. Zeig doch mal, was du hast. Als Dateianhang mit Nachmane *.c
BL schrieb: > weil so viel Code habe ich noch gar nicht > geschrieben. Es reicht ja, wenn der von Dir geschriebene Code größere Libraryfunktionen einbindet -- der 'F2013 ist beispielsweise gar kein guter Kandidat für Floatingpoint-Arithmetik. Mit nur 2 kiB Flash-ROM kann man keine großen Sprünge machen.
ui ui ui ^^ Gibt es in IAR die Möglichkeit, die Größe des compilierten Codes zu sehen? 2 KB Flash Memory ist nicht viel, stimmt. Als Code habe ich paar headerfiles mit defines drin und dann das USI_I2C.c file mit den state machines für den jeweiligen Befehl für das I2C Protokol. Als kleines Beispiel:
1 | int I2C_Write_1ByteRegister (int iCommand) |
2 | {
|
3 | static int siI2C_State = 0; |
4 | int iNACK_Flag = 0; |
5 | |
6 | switch (siI2C_State) |
7 | {
|
8 | case 0: //send start condition to slave |
9 | USI_LOW_BYTE_SHIFT_REGISTER = SET_START; |
10 | USI_CONTROL_REGISTER0 |= USI_LATCH_ENABLE + USI_DATA_OUTPUT_ENABLE; |
11 | USI_CONTROL_REGISTER0 &= ~USI_LATCH_ENABLE; |
12 | //send slave address to slave
|
13 | gcI2C_Slave_Address |= I2C_WRITE_TO_SLAVE_OPERATION; |
14 | USI_LOW_BYTE_SHIFT_REGISTER = gcI2C_Slave_Address; |
15 | USI_BIT_COUNTER_REGISTER = USI_COMMUNICATION_BITS_8; |
16 | //set next state
|
17 | siI2C_State = 1; |
18 | break; |
19 | |
20 | case 1: //receive address ACK / NACK |
21 | USI_CONTROL_REGISTER0 &= ~USI_DATA_OUTPUT_ENABLE; |
22 | USI_BIT_COUNTER_REGISTER = USI_COMMUNICATION_BITS_1; |
23 | //set next state
|
24 | siI2C_State = 2; |
25 | break; |
26 | ...
|
Die state machines haben wohl den Speicher gefüllt?
BL schrieb: > USI_I2C.c file mit den state machines für den jeweiligen Befehl #den# state machines? Wieviele sind es denn? Den Optimizer hast du aber schon eingeschaltet? für das > I2C Protokol. > > Als kleines Beispiel: > >
1 | > int I2C_Write_1ByteRegister (int iCommand) |
2 | > { |
3 | > static int siI2C_State = 0; |
4 | > int iNACK_Flag = 0; |
5 | >
|
6 | > switch (siI2C_State) |
7 | > { |
8 | > case 0: //send start condition to slave |
9 | > USI_LOW_BYTE_SHIFT_REGISTER = SET_START; |
10 | > USI_CONTROL_REGISTER0 |= USI_LATCH_ENABLE + |
11 | > USI_DATA_OUTPUT_ENABLE; |
12 | > USI_CONTROL_REGISTER0 &= ~USI_LATCH_ENABLE; |
13 | > //send slave address to slave |
14 | > gcI2C_Slave_Address |= I2C_WRITE_TO_SLAVE_OPERATION; |
15 | > USI_LOW_BYTE_SHIFT_REGISTER = gcI2C_Slave_Address; |
16 | > USI_BIT_COUNTER_REGISTER = USI_COMMUNICATION_BITS_8; |
17 | > //set next state |
18 | > siI2C_State = 1; |
19 | > break; |
20 | >
|
21 | > case 1: //receive address ACK / NACK |
22 | > USI_CONTROL_REGISTER0 &= ~USI_DATA_OUTPUT_ENABLE; |
23 | > USI_BIT_COUNTER_REGISTER = USI_COMMUNICATION_BITS_1; |
24 | > //set next state |
25 | > siI2C_State = 2; |
26 | > break; |
27 | > ... |
28 | >
|
Na ja. das sieht jetzt nur so weltbewegend aus. Aber im Grunde sind das nur ein paar Zuweisungen. Also nichts dramatisches. Das braucht ein paar Bytes, aber bis 2Kb ist da noch weit hin. Such nach effektiven Berechnungen! Dort könnte was unbeabsichtigtes stecken. Oder tu das, was Lothar vorgeschlagen hat: Häng deinen verd.... Code hier an. Dann helfen wir dir das Zeug auf Kandidaten durchzusehen. Das ist doch nicht so schwer. Wenn du vom Arzt einen Rat willst, gehst du ja auch selber hin, damit er sich die Sache mal selber ansehen kann.
Karl Heinz Buchegger schrieb: > #den# state machines? > Wieviele sind es denn? Es sind 5 statemachines. Für jeden Befehl eine. Siehe Funktionen unten: int I2C_SendCommand (int iCommand); int I2C_Write_1ByteRegister (int iRegister); int I2C_Write_2ByteRegister (int iRegister); int I2C_Read_1ByteRegister (int iRegister); int I2C_Read_2ByteRegister (int iRegister); In der main ist einfach eine kleine while-Schleife mit Befehlen. Zum Beispiel:
1 | //config. temp. sensor
|
2 | giDS1621_Sensor_Register = DS1621_ACCESS_CONFIG; |
3 | USICTL1 |= USIIFG; // Set flag and start communication |
4 | LOW_POWER_MODE_1; |
5 | __no_operation(); |
6 | Sleep(20); //give sensor time to write to EEPROM |
7 | |
8 | if (giI2C_ERROR) |
9 | {
|
10 | USI_ERROR (); |
11 | break; |
12 | }
|
13 | |
14 | //start temp. conversion
|
15 | giDS1621_Sensor_Register = DS1621_START_CONVERSION; |
16 | USICTL1 |= USIIFG; // Set flag and start communication |
17 | LOW_POWER_MODE_1; |
18 | __no_operation(); |
19 | Sleep(10); |
20 | if (giI2C_ERROR) |
21 | {
|
22 | USI_ERROR (); |
23 | break; |
24 | }
|
25 | ...
|
Gibt es in IAR die Möglichkeit, die Größe des compilierten Codes zu sehen?
Ich habe nur eine Berechnungen: giTimerA_Delay = (int)(iMilliseconds/500); Alles andere sind Zuweisungen für Register.
Ich habe jetzt unter "Optimizations" von Low auf High gestellt. Jetzt scheint etwas mehr Platz zu sein. Der Fehler ist weg. Würde aber gerne noch sehen, wieviel Platz denn da nun ist.
BL schrieb: > Ich habe jetzt unter "Optimizations" von Low auf High gestellt. > Jetzt scheint etwas mehr Platz zu sein. Der Fehler ist weg. > > Würde aber gerne noch sehen, wieviel Platz denn da nun ist. WIes beim IAR ist, weiß ich nicht. Aber die übliche Bezeichnung dafür ist: Du willst ein Map erzeugt haben, oder Memory Map. Und die Option müsste sich irgendwo bei den Linker Optionen finden.
Danke! Hab nun nen Map File erstellt. Ich schicks dir mal im Anhang. Nach der Aussage des Files, verbrauche ich 1,5k ROM Speicher. Mal suchen, was denn da soviel speicher frißt.... [Den Code selbst darf ich leider nicht senden. Sorry an alle!]
Du kannst auch das untere Message Fenster so umstellen das mehr beim Build angezeigt wird. Tool -> Options -> Messages -> Show build messages -> All
Also falls noch jemand die Antwort wissen möchte: Ich habe dem Code auf den Zahn gefühlt. Es sind tatsächlich die state machines. Benötigen 1k ROM Speicher. Können aber nicht kleiner programmiert werden. Böse böse... ^^ Vielen Dank euch fürs Helfen! BL
BL schrieb: > if (giI2C_ERROR) > { > USI_ERROR (); > break; > } BL schrieb: > __no_operation(); > Sleep(10); Wenn der ganze Code solche Dinge und weitere Überraschungen enthält, wundert mich dein Speicherproblem nicht.
Wie bitte? ^^ Was soll an dem oberen Code überraschend oder schlecht programmiert sein? Die Funktionsaufrufe???
BL schrieb: > LOW_POWER_MODE_1; > __no_operation(); > Sleep(20); //give sensor time to write to EEPROM kurze Fragen: Warum wird mitten im Ablauf (keine Verzweigung) der Low Power Mode gewechselt? Warum wird vor einem Delay ein NOP eingefügt? > if (giI2C_ERROR) > { > USI_ERROR (); > break; > } weitere Frage: Warum wird ein if Zweig am Ende unterbrochen? Ja, ja, ich weiß, der Compiler optimiert das eine oder andere. Aber man sollte im Groben schon wissen, was man tut.
Das break dient, um aus der while-Schleife auszubrechen. Bevor man sich Gedanken, um Low Power macht, sollte erstmal das Programm funktionieren. Ein __no_operation gefolgt vom sleep ist natürlich unschön...
Ihr solltet wissen, dass ihr euch grad über einen Code gedanken macht, der nur zu testzwecken geschrieben wurde, um das I2C Protokol zu testen und dann gelöscht wird. Hier kurz die Erklärung: Der Low-Power Mode wird nicht gewechselt. __no_operation(); <-- Diese Zeile ist nur für die IAR Workbench gedacht. War in den Beispiel Codes von Texas Instruments so angegeben. Das ist aber kein Low-Power Mode für den µCs. Sleep() <-- Sleep ist kein delay, sondern ein tatsächliches "sleep". Der µC geht da, der angegebenen Zeit entsprechend in Low-Power Mode und wird dann von einem Interrupt geweckt. Die if-Abfragen sind in einer while-Schleife, die mehrere Befehle hintereinander ausführt. Entsteht zwischendrin ein Error, wird die gesamte while-Schleife unterbrochen. -------------------- Zusatz: Also mein Speicherproblem ist ja im Grunde "behoben". Ich habe 1) die Optimierung von low auf high gesetzt 2) aus den 5 statemachines, eine gemacht. Damit habe ich 800 bytes gesparrt. Meine Sleep Funktion frisst natürlich auch bytes, aber ich möchte sie trotzdem nicht durch eine delay funktion austauschen. Danke für euer Interesse an meinem Problem! :)
BL schrieb: > Ihr solltet wissen, dass ihr euch grad über einen Code gedanken macht, > der nur zu testzwecken geschrieben wurde, um das I2C Protokol zu testen > und dann gelöscht wird. Sei doch froh, dass man es gut mit dir meint oder Mitleid hat. ;-D BL schrieb: > Der Low-Power Mode wird nicht gewechselt. und was soll dann die Zeilen: BL schrieb: > LOW_POWER_MODE_1; BL schrieb: > __no_operation(); <-- Diese Zeile ist nur für die IAR Workbench > gedacht. War in den Beispiel Codes von Texas Instruments so angegeben. > Das ist aber kein Low-Power Mode für den µCs. Du weisst nicht was NOP ist? LoL BL schrieb: > Sleep() <-- Sleep ist kein delay, sondern ein tatsächliches "sleep". Das war nicht gemeint. Ein NOP vor einem Delay, Sleep oder was auch immer ist einfach Blödsinn. BL schrieb: > Die if-Abfragen sind in einer while-Schleife, die mehrere Befehle > hintereinander ausführt. Entsteht zwischendrin ein Error, wird die > gesamte > while-Schleife unterbrochen. Das hört sich nach einem halben goto an. ;-D Meist lässt sich das durch else if lösen. Du hast ein massives Programmspeicherproblem. In den gezeigten Codefragmenten sind mehere unnütze und verwirrende Anweisungen. Wie sieht der Rest wohl aus? Wahrscheinlich reicht ein 1k Flash. :-DDD
Alter... @Optimizer: Hier der Original Code von Texas Instruments msp430x20x3_usi_06.c:
1 | ...
|
2 | while(1) |
3 | {
|
4 | USICTL1 |= USIIFG; // Set flag and start communication |
5 | LPM0; // CPU off, await USI interrupt |
6 | _NOP(); // Used for IAR |
7 | for (i = 0; i < 5000; i++); // Dummy delay between communication cycles |
8 | }
|
9 | ...
|
Oh Wunder, da steht auch zuerst LPM0 und dann _NOP() ... Was ist nun bitteschön falsch daran, diese beiden Zeilen in den eigenen Code zu übertragen???? Und als Kommentar zum NOP steht: USED for IAR. Genau das hab ich oben geschrieben.
BL schrieb: > Oh Wunder, da steht auch zuerst LPM0 und dann _NOP() Ja ja, manche MSP's haben Probleme aus einem LPM wieder aufzuwachen wenn hinter der LPM-Anweisung kein NOP steht. Das kann also schon seinen Sinn haben, genaueres verrät das Datenblatt.
BL schrieb: > Oh Wunder, da steht auch zuerst LPM0 und dann _NOP() ... > Was ist nun bitteschön falsch daran, diese beiden Zeilen in den eigenen > Code zu übertragen???? Dort wird auch ein Low Power Mode eingenommen, bis der direkt davor scharf gemachte USI Interrupt kommt. Wenn du es wie beim TI Beispiel machen möchtest, gehört NOP hinter dein Sleep. Sei doch froh, dass man es dir erklärt, anstatt mit Unwissenheit zu pralen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.