Why not (finally) expose main.cpp to the user ?

@CrossRoads: no.

##############################################################
#
# to activate this board, select it and use:
#
# 'Burn Bootloader' - 'w/ USBtinyISP' just once
# this makes sure the correct FUSE settings are used
#
8x8RGBLedMatrix1.name=8x8 RGB LED Matrix - ATmega168 / 16MHz Quartz / USBtiny
8x8RGBLedMatrix1.upload.maximum_size=16384
8x8RGBLedMatrix1.upload.speed=115200
8x8RGBLedMatrix1.upload.using=arduino:usbtinyisp
8x8RGBLedMatrix1.bootloader.low_fuses=0xFF
8x8RGBLedMatrix1.bootloader.high_fuses=0xDD
8x8RGBLedMatrix1.bootloader.extended_fuses=0x05

## just so the IDE doesn't throw an error
## it will be overwritten, but we need the correct FUSE settings
8x8RGBLedMatrix1.bootloader.path=optiboot
8x8RGBLedMatrix1.bootloader.file=optiboot_diecimila.hex
##

8x8RGBLedMatrix1.bootloader.unlock_bits=0x3F
8x8RGBLedMatrix1.bootloader.lock_bits=0x3F
8x8RGBLedMatrix1.build.mcu=atmega168
8x8RGBLedMatrix1.build.f_cpu=16000000L
8x8RGBLedMatrix1.build.core=arduino
#
#
#
##############################################################

If I want to do without a bootloader, I change the fuse settings, lockbits and the available flash size to respect that fact. Uploading works as usual.

Uploading is currently slower with an usbtiny than with optiboot. There is a trivial ‘patch’ for that, but it was not accepted… it involves adding the bitclock parameter ‘-B 1’ to the programmers.txt and a tiny modification in the java code that deals with uploading. This would increase upload speed at least 10x.

programmers.txt

usbtinyisp.name=USBtinyISP
usbtinyisp.protocol=usbtiny
usbtinyisp.bitclock=1

app/src/processing/app/debug/AvrdudeUploader.java

@@ -104,6 +104,10 @@ public class AvrdudeUploader extends Uploader  {
Map<String, String> programmerPreferences = target.getProgrammers().get(programmer);
List params = new ArrayList();
params.add("-c" + programmerPreferences.get("protocol"));
+
+ if (programmerPreferences.get("bitclock") != null) {
+ params.add("-B" + Integer.parseInt(programmerPreferences.get("bitclock")));
+ }

if ("usb".equals(programmerPreferences.get("communication"))) {
params.add("-Pusb");

I have given up getting anything added/patched in the IDE, it has proven to be pointless for me. I just complain here.

This will be ignored too I guess, but it is less painful for me overall.

[quote author=Nick Gammon link=topic=74927.msg565676#msg565676 date=1318313974] Let's just use main: [/quote] O.O I had no idea you could do that and this is 100% awesome. I just shaved 132 bytes off my sketch and now have enough space to implement a URL decode function (94 bytes) to fix that bug that's been annoying me for months.

See! It is useful.

CapnBry:
O.O I had no idea you could do that and this is 100% awesome. I just shaved 132 bytes off my sketch and now have enough space to implement a URL decode function (94 bytes) to fix that bug that’s been annoying me for months.

Glad that helped. Better not upgrade to version 1.0 though, unless they fix that .

You CAN use main() instead of setup() and loop(). Really, yes, you can.

void setup() { Serial.begin(9600); Serial.println("setup does not run"); }

void loop() { Serial.println("loop does not run"); }

int main() { init(); Serial.begin(9600); while (1) { Serial.println("My main is running"); delay(1000); } }

This works because main() is inside the core, which gets compiled to a ".a" library archive. If you use any function with the same name, the linker will put your copy into the final output, rather than the one from the library.

So go ahead and use main(). The ability to do so has been there all along. Just make sure you call init() to initialize the hardware, so things like millis() and delay() will work properly.

Well... this

void setup() {
  Serial.begin(9600);
  Serial.println("setup does not run");
}

void loop() {
  Serial.println("loop does not run");
  pinMode(13,OUTPUT);
}

int main() {
  init();
  Serial.begin(9600);
  while (1) {
    Serial.println("My main is running");
    delay(1000);
  }
}

compiles on 0022 and not on 1.0-rc1.

I've had a quick look on the compiler/linker parameters, but can't find a difference.

Error on 1.0-rc1:

avr-gcc -Os -Wl,--gc-sections -mmcu=atmega168 -o /tmp/build792419732568248348.tmp/sketch_oct16a.cpp.elf /tmp/build792419732568248348.tmp/sketch_oct16a.cpp.o /tmp/build792419732568248348.tmp/core.a -L/tmp/build792419732568248348.tmp -lm 
core.a(main.cpp.o): In function `main':
/XXX/arduino-1.0-rc1/hardware/arduino/cores/arduino/main.cpp:6: multiple definition of `main'
sketch_oct16a.cpp.o:sketch_oct16a.cpp:16: first defined here

This error vanishes when adding the 'weak' attribute as pointed out before.

I feel that if this compiles (works?) on 0022, it should do the same on 1.0

The difference is that the pin definition data structures have been moved (through a header file) into main.cpp.

Forgive my ignorance, but is using the 'weak' attribute for the linker to only way (correct?) to make it work again in 1.0 ?

Is the reason for the complaint that the user-provided main() is therefore not equivalent to the library one anymore?

Why do that? In fact why not change main.cpp from:

#include <WProgram.h>

int main(void)
{
	init();

	setup();
    
	for (;;)
		loop();
        
	return 0;
}

to:

void init ();
void setup ();
void loop ();

int main(void)
{
  init();
  setup();
  while (true)
    loop();
  return 0;
}

Then it compiles on its own without any header files, and will only be used if the user doesn’t supply their own main function.

madworm: Forgive my ignorance, but is using the 'weak' attribute for the linker to only way (correct?) to make it work again in 1.0 ?

That is one way. The other way would be to move the pin definition data structures to another module. Where they were (wiring_digital) is a good choice. I would move them to their own module.

Is the reason for the complaint that the user-provided main() is therefore not equivalent to the library one anymore?

Someone else will have to answer that one.

[quote author=Nick Gammon link=topic=74927.msg573068#msg573068 date=1318969360]Why do that? [/quote]

I believe it is an attempt to make the core more portable. The idea is to have the pins defined in a header file that is located and included when a sketch is built.

But I don't know why main.cpp was used to pull in the pin definitions.

In fact why not change main.cpp from ... Then it compiles on its own without any header files, and will only be used if the user doesn't supply their own main function.

I almost agree. There is some safety in using a common header file for function prototypes. Well, with overloading, maybe there isn't. Let me check ... never mind. I must be thinking of ObjectPascal.

I agree. The second version is a good alternative.

[quote author=Coding Badly link=topic=74927.msg573096#msg573096 date=1318970976] I believe it is an attempt to make the core more portable. The idea is to have the pins defined in a header file that is located and included when a sketch is built. [/quote]

Since the developers control what the IDE does when it compiles, why not just have it copy the pins file anyway? I mean, if they are going to copy main.cpp, why not copy pins_arduino.h as well? This seems a convoluted way of doing it.

I have no idea why it was done the way it was.

I believe the idea was to allow 3rd party boards to use the standard Arduino core more easily. All the pinout-specific stuff is supposed to go into a single header file, and boards.txt can specify the directory. So in theory, a board which only needs to customize pins could just add a directory and its own copy of pins_arduino.h, and not need to modify any files, except perhaps boards.txt.

Compiling the code into main.cpp was probably just an oversight? It very likely belongs in either wiring_digital.c (where it's actually used), or in its own dedicated .c file (as it was in prior to 1.0).

If you delete the ARDUINO_MAIN line from main.cpp, and add it into wiring_digital.c like this:

#define ARDUINO_MAIN
#include "wiring_private.h"
#include "pins_arduino.h"

I believe that solves this problem.

We can certainly move the pins_arduino.h include from main.cpp to some other file, if it helps. Just submit a issue / patch to the Google Code list: http://code.google.com/p/arduino/issues/list

Done, issue #691, including a patch! :)

http://code.google.com/p/arduino/issues/detail?id=691

Bump.

This patch became part of 1.0-rc2. Anyone who really cares about main() might want to give 1.0-rc2 a try before 1.0 officially releases?

http://code.google.com/p/arduino/wiki/Arduino1

This example compiles and works:

int main(void) {
  init();
  Serial.begin(9600);
  pinMode(2, INPUT);
  while(1) {
    int sensorValue = digitalRead(2);
    Serial.println(sensorValue);
  }
}

I see that all compiler warnings have been turned on, probably only for testing.

Some observations:

avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=100 -I/***/arduino-1.0-rc2/hardware/arduino/cores/arduino -I/***/arduino-1.0-rc2/hardware/arduino/variants/standard /***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.cpp -o/tmp/build4743758903281560802.tmp/IPAddress.cpp.o 
In file included from /***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.cpp:3:
/***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.h: In member function 'IPAddress::operator uint32_t()':
/***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.h:51: warning: dereferencing type-punned pointer will break strict-aliasing rules
/***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.h: In member function 'bool IPAddress::operator==(const IPAddress&)':
/***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.h:52: warning: dereferencing type-punned pointer will break strict-aliasing rules
/***/arduino-1.0-rc2/hardware/arduino/cores/arduino/IPAddress.h:52: warning: dereferencing type-punned pointer will break strict-aliasing rules
avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=100 -I/***/arduino-1.0-rc2/hardware/arduino/cores/arduino -I/***/arduino-1.0-rc2/hardware/arduino/variants/standard /***/arduino-1.0-rc2/hardware/arduino/cores/arduino/Tone.cpp -o/tmp/build4743758903281560802.tmp/Tone.cpp.o 
/***/arduino-1.0-rc2/hardware/arduino/cores/arduino/Tone.cpp:108: warning: only initialized variables can be placed into program memory area

The last one can be silenced by using 'const prog_uint8_t var_name' instead of 'const uint8_t PROGMEM var_name'.

See: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=57011

I'm using:

  • avr-gcc (GCC) 4.4.3
  • avr-libc 1.7.1

Thanks for making it work.

The PROGMEM issue seems identical to

http://code.google.com/p/arduino/issues/attachmentText?id=688&aid=6880000003&name=0004-Avoid-spurious-pgmspace-warnings.-See-http-gcc.gnu.o.patch&token=9f0e77f0e7d48a831b326a901e2ed403