-1

i have this blinking LED program (it flashes the L led every second)

#include <avr/io.h>
#include <util/delay.h>
#define DELAY 1000
int main (void) {
    DDRB |= _BV(DDB5);
    while(1) {
        PORTB |= _BV(PORTB5);
        _delay_ms(DELAY);
        PORTB &= ~_BV(PORTB5);
        _delay_ms(DELAY);
    }
    return 0;
}

this works fine but when i add a function as follows the L LED doesn't flash i intend it to. even when i remove all the code from the main function it still flashes the same way.

#include <avr/io.h>
#include <util/delay.h>
#define DELAY 1000
int main (void) {
    DDRB |= _BV(DDB5);
    while(1) {
        PORTB |= _BV(PORTB5);
        _delay_ms(DELAY);
        PORTB &= ~_BV(PORTB5);
        _delay_ms(DELAY);
    }
    return 0;
}

int test(){
    return 0;
}

i use avrdude to flash the program. the processor is atmega328p. this is the Makefile that i use

defualt:
    avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o speaker.c
    avr-gcc -o led.bin led.o
    avr-objcopy -O ihex -R .eeprom led.bin led.hex
    sudo avrdude -F -V -c arduino -p ATMEGA328p -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex
    rm led.bin
    rm led.o
    rm led.hex

i tried removing parameters,changing the return type,adding a prototype function, non of them worked.

  • Does any of your compile commands report an error? As you don't call that `test` function, the return type won't probably matter. I would expect the compiler to remove it completely, anyway. – Gerhardh Dec 11 '22 at 09:36
  • 1
    "even when i remove all the code from the main function it still flashes the same way." makes me suspect that you are editing the wrong file. Please add a `#error This is indeed compiled.` line before your includes. If you then do not get an error during compiling then you do not compile the file you are editing which is the same as saying you are not editing the file which you are compiling. – Yunnosch Dec 11 '22 at 09:40
  • It's very suspect that you are not passing the `-mmcu=` argument when you link your objects. I would suspect that GCC is not using the right linker script and linking in the correct startup code. What happens if you add that argument? Also, GCC normally produces an ELF file not a BIN file... can you run `file led.bin` to see what it really is? – David Grayson Dec 12 '22 at 18:48
  • A tip unrelated to your problem: The most modern AVR support toggeling an output Pin by just writing the bitmask to the `PIN` register (that saves the read, modify, write logic). So your while loop could be simplified to `PIN = _BV(PORTB5); _delay_ms(DELAY)` – vlad_tepesch Jan 17 '23 at 09:28

1 Answers1

1

If you paste your code below the main function you have to define a prototype like e.g.:

#define F_CPU 16000000UL
#define DELAY 1000

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

void blink(volatile unsigned char *port, unsigned char pin);

int main (void)
{
    DDRB |= _BV(DDB5);
    while(1) {
      
      blink(&PORTB, PINB5);

    }
    return 0;
}

void blink(volatile unsigned char *port, unsigned char pin)
{
    *port |= _BV(pin);
    _delay_ms(DELAY);
    *port &= ~(_BV(pin));
    _delay_ms(DELAY);
}

so the compiler knows the function header and later is getting linked.

volatile is needed cause PORTs are accessed directly in RAM

References:

sunriax
  • 592
  • 4
  • 16