I've just released Beta ver. 1.00 of Ddr-ArdMeg, a high performance, device driver library for Arduino Mega 2560 (ATMega 2560) and Moteino Mega (ATMega 1284p).
The library is tight, type safe, has high performance and is written entirely in C++11 (C-style). Most device setup functions compiles to a single, or a few assembler instructions. The library currently supports:
DIO per port
DIO per pin
External interrupts
Reading / writing internal EEPROM
A/D conversion (asynchron but not interrupt driven)
Buffered (asynchron) and non-buffered (synchron) serial communication
Buffered (asynchron) and non-buffered (synchron) SPI communication
Binary number notation (e.g. b0101)
Configurable resource utilization (mainly useful for Arduino Mega 2560)
Configurable pin name mappings (currently supports both boards)
The library is distributed as source code only (GPL v3) and only depends on GCC (tested with 4.9.2) and AvrLibc (1.8.1). No other dependencies. I've used Eclipse CDT during development and the library SHOULD be able to be used within Arduino IDE straight forward. However, the last time I tested the sketch compiler refused to compile. If anyone has any success, please let me now so that I can add some explanatory text to the documentation.
Currently, the documentation is NOT TO BE TRUSTED owing to major revisions of the code. However, I've added a few examples (separate download file) that I hope are useful. There are also a bunch of test cases in the SVN trunk that may be of help.
More info is available at the project web site (link above).
Feedback, comments, bug reports, ... is all welcome (there's a discussion forum at Sourceforge)
lonfield:
I've just released Beta ver. 1.00 of Ddr-ArdMeg, a high performance, device driver library for Arduino Mega 2560 (ATMega 2560) and Moteino Mega (ATMega 1284p).
Maybe my brain has taken the evening off, but what is the purpose of this? Who would use it? When? Why?
Well, besides the obvious purpose of performance and compact code, it's up to anyone to make up their own mind if to use the library for something or not. For my personal project it will end up being the foundation for an airborne telemetry system consisting of about 15 sensors, GPS, flash memory, display and a radio link. That's also the reason I've included support for the Moteino Mega (small, light & integrated radio).
Have you seen Cosa? Beautiful design, and very efficient.
I'll take a look at your library sometime... my NeoGPS might be easy to port. It doesn't really have any Arduino core references, except in the examples.
lonfield:
Well, besides the obvious purpose of performance and compact code, it's up to anyone to make up their own mind if to use the library for something or not.
I guess we are misunderstanding each other.
I still can't figure what sort of projects this would be useful in, or how it relates to other (perhaps more familiar) Arduino libraries.
For example, I know the Servo library is for servos and the RF24 library is for an nRF24 wireless transceiver. But my notion of "device driver" is something you have on a PC.
Delete HelloWorld/Include and HelloWorld/Source. This isn't absolutely necessary but none of the files in those folders will be used so having them in the sketch folder is pointless and will only lead to confusion.
In the folder HelloWorld, create a file named HelloWorld.ino
Open HelloWorld.ino in the Arduino IDE
Add this to HelloWorld.ino:
#include "Configure.h"
After doing the above I changed line 42 of main.cpp from:
init(SerialPort::SER_2);
to:
init(SerialPort::SER_0);
and line 45 from:
writeStr(SerialPort::SER_2,"Hello World!");
to
writeStr(SerialPort::SER_0,"Hello World!");
so I could get the output on Serial0 instead of Serial2. Of course that's not necessary, it was just more convenient for me that way.
I saw Cosa a few months ago and I think it should be a minor effort to port NeoGPS. After a quick look, I take it that NeoGPS is stream oriented and that would fit the buffered serial driver in Ddr-ArdMeg straight away with a minor addition of some glue code. I'll take a look at it when I start working on the telemetry application.
Thanks a lot for the help with the Arduino sketch! Really appreciated. I'll add another FAQ-item on the web site describing the procedure. Regarding the Sourceforge hosting it just happens to be that I already had another project there so the threshold for adding a new project was low.
Regarding what a device drive is, I quote Wikipedia:
"In computing, a device driver (commonly referred to simply as a driver) is a computer program that operates or controls a particular type of device that is attached to a computer. A driver provides a software interface to hardware devices, enabling operating systems and other computer programs to access hardware functions without needing to know precise details of the hardware being used."
In other words, a device driver is a software layer that provides a level of abstraction that is higher than the one provided by the raw hardware. A device in the context of Ddr-ArdMeg is any of the built-in peripheral devices provided by the specific MCU (UART, SPI, I2C, ports, ...). Device drivers are used by most OS:es but an OS is not a prerequisite.
The similarity between the Arduino sketch and the Ddr-ArdMeg version of "Hello World" is a feature, believe it or not. It shows that the Arduino IDE and Ddr-ArdMeg operates at basically the same level of abstraction. Now, the interesting part happens behind the scene. Unless my memory fails me, the Arduino sketch compiles to about 1.7 KB for a Moteino Mega. The Ddr-ArdMeg version compiles to 342 bytes. Of these 342 bytes, ~200 bytes are boot code, interrupt vector tables, etc. inserted by AVR-Libc. In other words, the "Hello world" program is ~150 bytes. Assuming a similar overhead for the Arduino sketch, we are talking about a factor of 10 in code size reduction. Execution speed will, for this example, be almost the same since the rate limiting step is the 9600 baud serial communication.
Obviously, this is a specific case and you can't expect 10 times less code for every program since the device centric parts are usually a fraction of the entire program. In any way, less memory will be used and execution speed will for certain be competitive. Who will need that? Well, I'm one for sure .
lonfield:
Unless my memory fails me, the Arduino sketch compiles to about 1.7 KB for a Moteino Mega. The Ddr-ArdMeg version compiles to 342 bytes. Of these 342 bytes, ~200 bytes are boot code, interrupt vector tables, etc. inserted by AVR-Libc. In other words, the "Hello world" program is ~150 bytes. Assuming a similar overhead for the Arduino sketch, we are talking about a factor of 10 in code size reduction.
Am I correct, then, to think that your code is an alternative to the Arduino IDE that compiles the same activities to a smaller code size?
I can see how that could be an advantage but I did not get any sense from your Original Post that that was the purpose of your program.
Yes Robin2, thats basically it and in this specific case small size also translates to execution speed. I suppose I could have been clearer about that.
Your correct it doesn't, at least not for now. I haven't written the driver for the timers yet for the simple reason that I wanted to get the code out in the open before adding support for yet another periferal. Putting together a release force oneself to finish all those clean-up tasks that otherwise would just be ignored/forgotten...
After I've finished the documentation (next task in line) it's either the timers or the i2c-bus. I probably need both in my own project but currently I feel that the i2c-bus adds less usability than the timers. I2c is just another bus and the library already supports SPI and serial. Hence, timers are the stronger candidate.
lonfield:
Unless my memory fails me, the Arduino sketch compiles to about 1.7 KB for a Moteino Mega.
Robin2's code on Arduino IDE 1.8.2/Arduino AVR Boards 1.6.18 compiles to:
Sketch uses 1750 bytes (0%) of program storage space. Maximum is 253952 bytes.
Global variables use 192 bytes (2%) of dynamic memory, leaving 8000 bytes for local variables. Maximum is 8192 bytes.
So that's about what you remember. However:
lonfield:
The Ddr-ArdMeg version compiles to 342 bytes.
With the changes I mentioned above, HelloWorld compiles in the Arduino IDE to:
Sketch uses 1678 bytes (0%) of program storage space. Maximum is 253952 bytes.
Global variables use 338 bytes (4%) of dynamic memory, leaving 7854 bytes for local variables. Maximum is 8192 bytes.
I suspect the difference may be that the Arduino IDE automatically adds the line:
#include <Arduino.h>
to HelloWorld.ino.
Regarding the confusion over the term "device driver library": I think in the Arduino world we would call this a core. For example, here is the one used by Arduino AVR Boards: https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/cores/arduino
Though some of the files in DdrArdMeg are analogs of the libraries included with Arduino hardware packages. So basically we have replacements in DdrArdMeg of the Arduino files/libraries:
Analog.h - hardware/arduino/avr/cores/arduino/wiring_analog.c
Binary.h - hardware/arduino/avr/cores/arduino/binary.h
Eeprom.h - hardware/arduino/avr/libraries/EEPROM/src/EEPROM.h
ExtIrq.h - hardware/arduino/avr/libraries/EEPROM/src/WInterrupts.c
Mcu.h - hardware/arduino/avr/libraries/EEPROM/src/wiring_digital.c
Pin.h - hardware/arduino/avr/libraries/EEPROM/src/wiring_digital.c
Port.h - hardware/arduino/avr/libraries/EEPROM/src/wiring_digital.c
Serial.h, etc. - hardware/arduino/avr/libraries/EEPROM/src/HardwareSerial.h, etc.
Spi.h - hardware/arduino/avr/libraries/SPI/src/SPI.h, etc.
They all seem to differ from the standard Arduino API.
If compatibility with the Arduino IDE was a goal you might consider creating a hardware package, as Cosa has done. This would allow you to define your own Arduino.h and pins_arduino.h files and thus likely cut out the extra overhead seen when using DdrArdMeg as a library with Arduino AVR Boards. There is more information on this here:
Robin2:
Is there some technical reason why the examples do not use the standard Arduino style with setup() and loop()?
If they did I think it would make the whole thing more accessible to Arduino users?
...R
No technical reason. I just felt that it wouldn't add the example per se. It's also trivial to add a setup() and a loop() to the main() in the example in the same way as it is done in Arduino's main.cpp.
Yes, Arduino.h is a major contributor to the sketch size, though not the only one.
Compatibility with the Arduino was not one of my design goals (sorry ). The goal, relative Arduino, is to have a similar level of abstraction so that it wouldn't be too difficult to alter between the two. From a technical view point it's also not really feasible to make Ddr-ArdMeg compatible with the Arduino API. For example, Ddr-ArdMeg has a more stringent approach regarding type safety. The main reason being to reduce the probability for bugs. This won't translate well to the Arduino API, which in many cases uses regular, unscoped integers.
Regarding hardware package, I've limited the support to the line of MCUs having the same architecture as ATMega 2560. However, the Configure.h file you mentioned earlier adds support for defining various pin naming schemes as well as taylorization of specific peripherals (quantities, buffer sizes and some) based on the specific needs and/or the MCU used.