changing a variable

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello all

I have write this code but the "i" variable is changing in the program

this is th code:

 unsigned int i,j;
    //for(i=0;i<1;i++){
            
            i=3;
            UDR=i;
            delay_ms(2);
            UDR=0xff;;
            delay_ms(2);
            address_page=0;
            address_home=0;
            address=(address_page << ZPAGELSB) | (address_home<<1);                                             
            #asm
                MOVW R30,R4       //R5,R4--->R31,R30  (copy to Z register)
                LDI R16,3         //SPMCR=3
                OUT 0x37,R16      //0x37=SPMCR
                SPM
           #endasm      
           while (SPMCR&1);   
       for(j=0;j<PageSize;j++){ 
          
            address_page=i;      //page=i 
            UDR=i;
            delay_ms(2);
            address_home=j;      
            address=(address_page << ZPAGELSB) | (address_home<<1);                                 
            data=*buffer++;      //first return *buffer=mohtavayebuffer then ++ address of buffer
             
           #asm 
                MOVW R30,R4      //R5,R4--->R31,R30  (copy to Z register)
                MOVW R0, R2      //R1,R0= data
                LDI R16,1        //SPMCR=1
                OUT 0x37,R16     //0x37=SPMCR
                SPM    
           #endasm
          while (SPMCR&1);                  
      }      
          
          UDR=0xff;
          delay_ms(2);
          UDR=i;
          delay_ms(2);
          address_page=i; 
          
          address_home=0;
          address=(address_page << ZPAGELSB) | (address_home<<1);                        
     #asm 
          MOVW R30,R4
          LDI R16,$05
          OUT 0x37,R16
          SPM
          NOP
          LDI R16,$11
          OUT 0x37,R16
          SPM            //enable RWW for reading
     #endasm
          while(SPMCR&1);

 

 

but this is the output

 

03 FF 03 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
01 01 FF 01

 

 

the i variable is changing from 3 to 1

why??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is that the actual code in your AVR? It should not build, and the compiler will generate an error since you commented out the FOR statement at the beginning of the code.

If your actual code does not have the '//' marks then that for loop is invrementing variable 'i'.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:

Is that the actual code in your AVR? It should not build, and the compiler will generate an error since you commented out the FOR statement at the beginning of the code.

If your actual code does not have the '//' marks then that for loop is invrementing variable 'i'.

Jim

 

It is not problem because the For statement is commented because this loop execute only 1 ; for i=3

but why i will be changed in it?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is that ALL your code for the routine?

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why? Have you traced your code in the Atmel Studio simulator? That might enlighten you - especially since you're playing with registers the compiler might actually be using for something. Why are you using inline assembler when avr-gcc has a number of intrinsics to help with bootloader code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
Is that ALL your code for the routine? Jim

this is my all code and my goal is write only 1 page of flash (page=3)

 

#include <mega8.h>
#include <stdio.h>
#include <delay.h>
//
//
//----------------Global Variable-------------------
//
register unsigned int data @2;
register unsigned int address @4;
unsigned int address_page,address_home;
#define ZPAGELSB 6
#define PageSize 32

//
//
//--------------------------------------------------
//
//
unsigned char flag_blink;
interrupt [TIM1_OVF] void timer1_ovf_isr(void){
     static unsigned int i=0;
     if(++i>=500) {i=0;flag_blink=1;}
     TCNT1=-1000;
}
//----------------BootLoad Func---------------------
//
void BootLoad(unsigned int *buffer){ 
    unsigned int i,j;
    //for(i=0;i<1;i++){
            
            i=3;
            UDR=i;
            delay_ms(2);
            UDR=0xff;;
            delay_ms(2);
            address_page=0;
            address_home=0;
            address=(address_page << ZPAGELSB) | (address_home<<1);                                             
            #asm
                MOVW R30,R4       //R5,R4--->R31,R30  (copy to Z register)
                LDI R16,3         //SPMCR=3
                OUT 0x37,R16      //0x37=SPMCR
                SPM
           #endasm      
           while (SPMCR&1);   
       for(j=0;j<PageSize;j++){ 
          
            address_page=i;      //page=i 
            UDR=i;
            delay_ms(2);
            address_home=j;      
            address=(address_page << ZPAGELSB) | (address_home<<1);                                 
            data=*buffer++;      //first return *buffer=mohtavayebuffer then ++ address of buffer
             
           #asm 
                MOVW R30,R4      //R5,R4--->R31,R30  (copy to Z register)
                MOVW R0, R2      //R1,R0= data
                LDI R16,1        //SPMCR=1
                OUT 0x37,R16     //0x37=SPMCR
                SPM    
           #endasm
          while (SPMCR&1);                  
      }      
          
          UDR=0xff;
          delay_ms(2);
          UDR=i;
          delay_ms(2);
          address_page=i; 
          
          address_home=0;
          address=(address_page << ZPAGELSB) | (address_home<<1);                        
     #asm 
          MOVW R30,R4
          LDI R16,$05
          OUT 0x37,R16
          SPM
          NOP
          LDI R16,$11
          OUT 0x37,R16
          SPM            //enable RWW for reading
     #endasm
          while(SPMCR&1);
      //}
                          
}

unsigned int i;
void main(void){
    unsigned int pro[32];

{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=Out Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRB=(1<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=0 Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=(0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1000/000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 65/504 ms
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x20;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0<<AS2;
TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(1<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x33;


// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
SFIOR=(0<<ACME);

// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Global enable interrupts
#asm("sei")
}
    
    PORTB.7=1;
    delay_ms(1000);
    PORTB.7=0;
    delay_ms(1000);
    PORTB.7=1;
    delay_ms(1000);
    PORTB.7=0;
    delay_ms(1000);
    
    for(i=0;i<500;i++) pro[i]=0x1234;
    BootLoad(pro);    

    while(1){

    if(flag_blink) {flag_blink=0;PORTB.7=!PORTB.7;}

    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Why? Have you traced your code in the Atmel Studio simulator? That might enlighten you - especially since you're playing with registers the compiler might actually be using for something. Why are you using inline assembler when avr-gcc has a number of intrinsics to help with bootloader code?

 

I am using codevision

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That explains a lot. Still, you can simulate your code in Atmel Studio. My guess is Codevision doesn't appreciate you changing register contents in your inline assembler. What does the Codevision manual say about inline assembler rules?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At which point its value changes?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

why are you trying to re-invent the wheel? There's an example bootloader from hpinfotech (Codevision authors) which should answer all your questions.

http://www.hpinfotech.ro/cvavr-e...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
My guess is Codevision doesn't appreciate you changing register contents in your inline assembler.
+1

 

Somewhere in your compiler manual it will talk about "ABI" (Application Binary Interface) which are the rules about how the compiler uses the machine registers and what restrictions there are about how you can change them in Asm sections. Ultimately you could just start by PUSHing every register you are about to use then POP them in reverse order afterwards.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CodeVision is as lenient [probably] on register usage in inline ASM as any other AVR compiler.  That said, indeed OP picked pretty much one of the wo0rst candidates by tromping R16 -- which usually contains the first local variable which is indeed i in this case.

The registers R0, R1, R22, R23, R24, R25, R26, R27, R30 and R31 can be freely used in assembly routines.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sat. Jun 15, 2019 - 03:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok,solved by defining unsigned char i @55;

Allocation a variable will be solve this problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hasanzadeh99 wrote:

Ok,solved by defining unsigned char i @55;

Allocation a variable will be solve this problem.

 

Why don't you address the core problem and fix your inline assembler code? Your fix sound like a hack that will come back to bite you someday.

 

Besides, I gave you an example, why did you not follow it?

Last Edited: Sun. Jun 16, 2019 - 07:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just had a quick look at you code and if you just push R16 before LDI R16,xx and after SPM pop it back it should work. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hasanzadeh99 wrote:
Ok,solved by defining unsigned char i @55;

And as soon as that "55" address is used by any update you make to your program, then your code breaks again.

 

There are many ways to do "clean" embedded ASM, and no contortions are needed.  Perhaps the simplest would be to use one of the allowed registers in the list as your temporary, instead of R16.  Then it would >>really<< be solved.

 

[edit]  I've posted before that CV lets you control nearly the whole AVR.  R2-R14 can be used for global register/bit variables, so you the programmer have full control.

R16-R22 (or so) are used for C locals in the order of definition, so that can be divined also.  Then there are the listed "scratchable" registers.

 

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sun. Jun 16, 2019 - 02:51 PM