Functions not working correctly with gcc

I’m having a problem calling a function multiple times when the same parameters are passed to it. I am using AtTiny24 with AVR Studio 4.15 build 623. The function will work correctly the first time and again as long as the parameters passed to it are different. For example my WriteLcd() function, if I do

WriteLcd(“MSG”,3); //works fine

WriteLcd(“MSG1”,4); //Works fine

WriteLcd(“MSG”,3); //Stops Working and prints // to the LCD

WriteLcd(“MSG2”,4); //Works fine

WriteLcd(“MSG2”,4); //Stops Working and prints // to the LCD

Like wise if I do

WriteLcd(string,strlen(string)); //Works fine

WriteLcd(string,strlen(string)); //Stops Working and prints // to the LCD

I have tried setting different optimizations with no luck. Any help would be appreciated.

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

// LCD is connected to PA0 
#define LCDPIN 0

// Button is connected to PA1
#define BTNPIN 1

//Write string to LCD at 9600 baud
void WriteLcd(char *string,int len);
void WriteLcd(char *string,int len)
{
	int bitloop,charloop;
	for(charloop=0;charloop<len;charloop++)
	{
		PORTA&=~(_BV(LCDPIN)); //Start Signal
		_delay_us(104);
		for(bitloop=0;bitloop<8;bitloop++)
		{
			if(string[charloop]&0x01)
			{
				PORTA |= _BV(LCDPIN);
			}
			else
			{
				PORTA&=~(_BV(LCDPIN));
			}
			string[charloop]>>=1;
			_delay_us(104);
		}
		PORTA |= _BV(LCDPIN); //Stop Signal
		_delay_us(104);
	}
}
int main(void)
{
	DDRA=0xFD; // Pin A1 input, others output
	PORTA = 0x03; // Enable internal pull-up resistor on PA1 and set others low
	char string[]="Hello";
	_delay_ms(300);
	WriteLcd("HI",2); //prints fine
	WriteLcd("HI",2); //prints garbage
	
	while(1)
	{
		
		if(bit_is_clear(PINA, BTNPIN))
		{	
			WriteLcd(string,6);
			while(bit_is_clear(PINA, BTNPIN));
		}

	}
	
	return 0;
}

old_dave:
I’m having a problem calling a function multiple times when the same parameters are passed to it. I am using AtTiny24 with AVR Studio 4.15 build 623. The function will work correctly the first time and again as long as the parameters passed to it are different. For example my WriteLcd() function, if I do

WriteLcd(“MSG”,3); //works fine

WriteLcd(“MSG1”,4); //Works fine

WriteLcd(“MSG”,3); //Stops Working and prints // to the LCD

WriteLcd(“MSG2”,4); //Works fine

WriteLcd(“MSG2”,4); //Stops Working and prints // to the LCD

Like wise if I do

WriteLcd(string,strlen(string)); //Works fine

WriteLcd(string,strlen(string)); //Stops Working and prints // to the LCD

I have tried setting different optimizations with no luck. Any help would be appreciated.

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

// LCD is connected to PA0
#define LCDPIN 0

// Button is connected to PA1
#define BTNPIN 1

//Write string to LCD at 9600 baud
void WriteLcd(char *string,int len);
void WriteLcd(char *string,int len)
{
int bitloop,charloop;
for(charloop=0;charloop<len;charloop++)
{
PORTA&=~(_BV(LCDPIN)); //Start Signal
_delay_us(104);
for(bitloop=0;bitloop<8;bitloop++)
{
if(string[charloop]&0x01)
{
PORTA |= _BV(LCDPIN);
}
else
{
PORTA&=~(_BV(LCDPIN));
}
string[charloop]>>=1;
_delay_us(104);
}
PORTA |= _BV(LCDPIN); //Stop Signal
_delay_us(104);
}
}
int main(void)
{
DDRA=0xFD; // Pin A1 input, others output
PORTA = 0x03; // Enable internal pull-up resistor on PA1 and set others low
char string=“Hello”;
_delay_ms(300);
WriteLcd(“HI”,2); //prints fine
WriteLcd(“HI”,2); //prints garbage

while(1)
{
	
	if(bit_is_clear(PINA, BTNPIN))
	{	
		WriteLcd(string,6);
		while(bit_is_clear(PINA, BTNPIN));
	}

}

return 0;

}

I can’t see anything obvious, but

in the bit shift loop, I’d code it to copy string[n] to a byte, then shift that byte rather than shifting the called parameter which is a constant stored in RAM.

Or use a bit mask that shifts from 0x01 to 0x80 then and that with the called string’s char. Some compilers would prohibit altering a constant like “HI”.

Note also that if you have a lot of strings, you should tell the compiler to store them in flash. As is, they’ll be stored in flash and copied to RAM in the C startup.

PORTA&=~(_BV(LCDPIN));

makes me nervous, versus

PORTA &= ~(_BV(LCDPIN));

The _BV() macro was retired long ago. Most often you see instead something like

PORTA &= ~(1<<LCDPIN);

Note too that a string constant in C by definition has a null byte added to the end, so that “HI” is stored as three bytes, the last being 0. So you can loop until you see that null, rather than using a count.

Thank you for your help. The problem was resolved by copying the value into a byte first like you suggested.