Strange error regarding functions

Hi,

I’m trying to program the Arduino from the command line, without using the Wiring library. I have some code which is supposed to turn a LED on if a potentiometer is over the middle position. My code is like this:

EDIT: I could resolve this by declaring the function as attribute((section(".data"))). But then GCC gave a warning about:

"/tmp/cciIMEse.s: Assembler messages:
/tmp/cciIMEse.s:8: Warning: ignoring changed section attributes for .data"

And when I uploaded my HEX file, the Arduino entered an infinite loop… it’s just blinking the LED very rapidly, and I can’t get it out of that stage (I suspect it encounters a ‘segfault’ kind of error and resets constinuously… But it can’t see avrdude. Neither the command-line one, neither when I try to use the IDE.)

EDIT #2:
I solved it like this:

I removed the AVR chip from the Arduino, but powered up the board in order to keep the serial chip communicating via USB. Then I wrote a fixed program, compiled it to HEX and started avrdude. When avrdude just started, I suddenly plugged back the AVR into the socket and voilá! avrdude progammed the chip before it could even enter the reset loop.

Thanks for all your help anyway!

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

#define analog_readval(pin) \
({ \
	unsigned char l, h, r; \
	r = (ADMUX & 0xf0) | (pin & 0x0f); \
	ADMUX = r; /* select the input channel */ \
	ADCSRA |= _BV(ADSC); \
	loop_until_bit_is_clear(ADCSRA, ADSC); \
	/* must read the low ADC byte before the high ADC byte */ \
	l = ADCL; \
	h = ADCH; \
	((unsigned short)(((unsigned short)h << 8 ) | l)); \
})

int main()
{
	/* internal pull-ups interfere with the ADC. disable the
	 * pull-up on the pin if it's being used for ADC. either
	 * writing 0 to the port register or setting it to output
	 * should be enough to disable pull-ups. */
	 PORTC = 0x00;
	 DDRC = 0x00;
	/* unless otherwise configured, arduinos use the internal Vcc
	 * reference. MUX 0x0f samples the ground (0.0V). */
	 ADMUX = _BV(REFS0) | 0x0f;
	/*
	 * Enable the ADC system, use 128 as the clock divider on a 16MHz
	 * arduino (ADC needs a 50 - 200kHz clock) and start a sample. the
	 * AVR needs to do some set-up the first time the ADC is used; this
	 * first, discarded, sample primes the system for later use.
	 */
	 ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADSC);
	/* wait for the ADC to return a sample */
	 loop_until_bit_is_clear(ADCSRA, ADSC);

	DDRB |= 1 << 5;
	while (1)
	{
		/*
		PORTB |= 1 << 5;
		_delay_ms(500);
		PORTB &= ~(1 << 5);
		_delay_ms(500);
		*/
		unsigned short adc_val_curr = analog_readval(3);
		if (adc_val_curr > 511)
		{
			PORTB |= 1 << 5;
		}
		else
		{
			PORTB &= ~(1 << 5);
		}
	}
	
	return 0;
}

And it works perfectly, as I expect it! However, when I try to define ANY function other than main(), I experience an error: although the program compiles, links, uploads perfectly, it doesn’t work! The LED never lights up. If I remove the function, it works again. I suppose there’s a problem with the GCC/avr-objcopy/avrdude, but I can’t for the world figure out what it is.

Thanks for any help.

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

You're doing this in the Arduino IDE? rename 'main' to 'loop' and see how it goes.

I don't think he's using the IDE.

I'm trying to program the Arduino from the command line

Can you post the function you say is causing you problems ?

The problematic function is defined as:

int fc_wtf() { return 0; }

Well, what I meat to say is let’s see the problematic code in its entirety, of course :stuck_out_tongue:

See the update... so the AVR is continuously crashing and I can't exit this infinite loop... it doesn't repsond to the programmer...

I’m trying to program the Arduino from the command line, without using the Wiring library.

Why?

I’m trying to program the Arduino …

Which Arduino?

I have some code which is supposed to turn a LED on if a potentiometer is over the middle position.

What circuit are you using?

H2CO3:
The problematic function is defined as:

int fc_wtf() { return 0; }

Can you post the code with the function in it? Do you call this function? Where is it located?


#define analog_readval(pin) \

({
unsigned char l, h, r;

h = ADCH;
((unsigned short)(((unsigned short)h << 8 ) | l));
})

Why “define” a function like this?


	((unsigned short)(((unsigned short)h << 8 ) | l));

What does this line do?

((unsigned short)(((unsigned short)h << 8 ) | l));

What does this line do?

I think this piece of code can provide an answer:

void setup() {
    int k = ({ int b = 1; b; });
    
    Serial.begin(9600);
    Serial.println(k, DEC);
}

void loop() {
}

The serial terminal shows: 1

Look closer at the #define: there’s a code block inside parentheses, like ( { statements; expression; } )
The whole thing evaluates to the value of the last expression.

Why?

Just because. (first, for curiosity; second, I'd like to use it with make, but the Wiring library is broken when I compile it without the Arduino IDE, even with exactly the same commands as reported in its verbose mode.)

Which Arduino?

Arduino Duemilanove with ATMega 328 P.

What circuit are you using?

Only the builtin LED on pin 13.

Can you post the code with the function in it? Do you call this function? Where is it located?

When my first problem appeared, I didn't call this function at all. I experienced that I broke the program by only inserting a function definition, without even calling it in main(). But I could solve this by adding attribute((section(".data"))) to the function definition. But now, as I wrote in the edit, the program with changed section attributes breaks the program and hangs the AVR (it continuously resets and avrdude can't access it).

Why "define" a function like this?

That was my first approach to avoid functions, and it worked.

What does this line do?

It's a GCC extension; ({ }) block expressions evaluate to the last statement within them.

H2CO3:

Can you post the code with the function in it? Do you call this function? Where is it located?

When my first problem appeared, I didn't call this function at all.

You want help, but you aren't prepared to post the problem code, is that it?

H2CO3:

Why "define" a function like this?

That was my first approach to avoid functions, and it worked

Why ever do you want to "avoid functions"? They are fundamental to programming.

mromani: Well, what I meat to say is let's see the problematic code in its entirety, of course :P

What he said.

As I wrote above, I wanted to avoid functions because they broke my program. It was meant to be a temporary workaround. (Please don’t give me a lecture on good programming techniques. I’m an experienced C programmer, I’m only having this issue with Arduino.)

Sorry, I forgot the code. Here you are:

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


__attribute__((section(".data")))
unsigned int analog_readval(pin)
{
	unsigned char l, h, r;
	r = (ADMUX & 0xf0) | (pin & 0x0f);
	ADMUX = r; /* select the input channel */
	ADCSRA |= _BV(ADSC);
	loop_until_bit_is_clear(ADCSRA, ADSC);
	/* must read the low ADC byte before the high ADC byte */
	l = ADCL;
	h = ADCH;
	return ((unsigned short)(((unsigned short)h << 8 ) | l));
}

__attribute__((section(".data")))
void analog_init()
{
	/* internal pull-ups interfere with the ADC. disable the
	 * pull-up on the pin if it's being used for ADC. either
	 * writing 0 to the port register or setting it to output
	 * should be enough to disable pull-ups. */
	 PORTC = 0x00;
	 DDRC = 0x00;
	/* unless otherwise configured, arduinos use the internal Vcc
	 * reference. MUX 0x0f samples the ground (0.0V). */
	 ADMUX = _BV(REFS0) | 0x0f;
	/*
	 * Enable the ADC system, use 128 as the clock divider on a 16MHz
	 * arduino (ADC needs a 50 - 200kHz clock) and start a sample. the
	 * AVR needs to do some set-up the first time the ADC is used; this
	 * first, discarded, sample primes the system for later use.
	 */
	 ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0) | _BV(ADSC);
	/* wait for the ADC to return a sample */
	 loop_until_bit_is_clear(ADCSRA, ADSC);
}

int main()
{
        analog_init();
	DDRB |= 1 << 5;
	while (1)
	{
		/*
		PORTB |= 1 << 5;
		_delay_ms(500);
		PORTB &= ~(1 << 5);
		_delay_ms(500);
		*/
		unsigned short adc_val_curr = analog_readval(3);
		if (adc_val_curr > 511)
		{
			PORTB |= 1 << 5;
		}
		else
		{
			PORTB &= ~(1 << 5);
		}
	}
	
	return 0;
}

attribute((section(".data")))
unsigned int analog_readval(pin)
{

Forcing the linker to place your code in the data section essentially creates a corrupt image. That alone is enough to badly break your program. Remove the section attribute from your functions. The compiler correctly marks your functions for the text section.

H2CO3:
I’m only having this issue with Arduino.)

Well not really. I can make an LED blink with an Arduino.

I wanted to avoid functions because they broke my program.

I don’t normally need to avoid functions.

Since this is something to do with not using the Arduino IDE perhaps it is better addressed to the AVR Freaks forum?

I mean, I like to help people solve their problems, but your post is basically about “I wrote and it doesn’t work”.

Thanks for your answer. (However I think the assembler done the things the right way; GCC emitted a warning saying "ignoring changed section of XXX".) However, I still can't make my board to communicate with the programmer... Any advice on that?

And for @Nick Gammon: All right, I'm going to ask this an the avrfreaks forum.

(note: I could make the LED blink. It even worked with the #define macros. Let me not repeat myself what was causing and what problem.)

If you aren't using the IDE, the problem could be compiler options. Check the default calling convention used as mixing them can be bad.

Thanks, I solved it in the meantime :)