Arduino-Lite Lightweight AVR library(1)

We are glad to introduce the Arduino-Lite to you. Arduino-Lite is a lightweight high-performance firmware library for AVR MCUs, which is developed based on the original Arduino project. We make it easy to use, just like the Arduino. Compared to the original library, Arduino-Lite generates smaller binaries and perform faster. And now, we are honored to introduce the Arduino-Lite to the public, and to make it open source. The open source version of Arduino-Lite can be downloaded at Google Code:http://code.google.com/p/arduino-lite/ This is the first one of the series articles. Detailed usage of Arduino-Lite will be posted soon.  

0. Supported Devices

Besides the standard Arduino controller boards based on Atmega328/168, all third-party boards using the following AVR chips are supported. We also published a driver-less AVR/51 programmer called RP USB Connector which is used internally by RoboPeak Team. The firmware of RP USB Connector is also developed with the Arduino-Lite library.

1. Why yet another library, and why to use it

Arduino and Arduino-Lite are both written with C++/C, and based on avr-gcc, but the Arduino-Lite has some pretty advantages:
  • Very very lightweight
Most binaries based on Arduino-Lite are 50% smaller than which based on Arduino.
  • High Efficiency
Many functions provided by Arduino-Lite, such as DIGITAL_WRITE, which is equivalent to the digitalWrite in the Arduino, implemented by only one AVR instruction.
  • More AVR chips and frequencies are supported
Besides Atmega8(A), Atmega168(PA), Atmega328(PA), Atmega1280, Arduino-Lite also supports Attiny2313, Attiny26, Atmega48(PA), Atmega88(PA)
Working frequencies supported by Arduino-Lite are ranging from 1Mhz to 20Mhz.
However, Arduino-Lite advances in following features as well:
  • Self-contained, no third-party tools, compilers or libraries dependencies.
With Arduino-Lite, the only tool you need to develop, compile or burn to devices is the common text editor, which is delivered by most modern operating system. Avr-gcc(WINAVR) and relative libraries comes with the Arduino-Lite package.
  • Flexible and easy-to-integrate Makefile-based compiling system, but no more Makefile composing or generating operations are required.
The easiest way to create a new Arduino-Lite project is decompress the template and rename it. You can place your code in any place in the project directory. And Arduino-Lite will compile your project properly. You don’t need to modify/compose/generate Makefile anymore.
 

1.0 Who and when to use Arduino-Lite

We think Arduino-Lite will be perfect choice in following situations:
  • Binary size or device cost sensitive, such as situations have to use Attiny or Atmega48 which contain small ROMs.
  • Performance sensitive, such as some real-time applications like industry controlling and robot controlling
  • Make gurus or IDE fans
  • Interested in Arduino/AVR, expecting a better IDE than the Arduino IDE and more effective firmware library
  • Developing firmware for those devices and frequencies not supported by Arduino in Arduino-way.
Arduino-Lite might not be suitable for:
  • Who don’t like command line or Makefiles (We are planing to make Arduino-Lite to support the Arduino IDE)
  • Whose projects are based on third-party Arduino libraries

1.1 Advantages shared by Arduino and Arduino-Lite

It is easy to do some common IO operations with Arduino, such as digitalWrite() digitalRead() and analogWrite(). This makes e-artists easier to develop their artworks, not requiring them to be familiarly with registers like DDR and PIN. Hobbyists without any background in MCU development can access the PWM features without knowing the working modes of the timers. For instance, developing with the standard avr-gcc (WINAVR), developers need to write the following code to make the LED fading:
1
2
3
4
5
6
7
8
9
10
11
12
13
//Set PWM mode: fast mode for timer 0
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
//set timer 0 prescale factor to 64
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
sbi(DDRB, PB1);
sbi(TCCR, COM11);
unsigned char led_brightness = 0;
for (led_brightness=0; led_brightness = 255; led_brightness++)
{
OCR01 = led_brightness;
}
Above code require the developer understand the name and usage of registers, what harden the development. Developers, even if experienced, might forget the detailed usage of some register.What’s more, registers of different AVR chips are differing from each other. Based on Arduino, code can be simple like this:
1
2
3
4
5
6
7
pinMode(9, OUTPUT);
unsigned char led_brightness = 0;
for (led_brightness=0; led_brightness = 255; led_brightness++)
{
analogWrite(9, led_brightness);
}
Arduino makes code simple and expressive, and makes it compilable across different chips as well. We think the following features make the Arduino excellent:
  • Wrap common operation into functions, to hide the difference of devices
  • Renaming AVR IO pins to a serial number; compared to names like PB1 and PC3, it is quite easier to use. This feature hides the different pin binding of chips, and makes programs cross-platform.
The above advantages make the Arduino widely used. While developing the Arduino-Lite, we inherits these features. The code base on Arduino-Lite with the same functionality looks like this:
1
2
3
4
5
6
7
PIN_MODE(9, OUTPUT);
unsigned char led_brightness = 0;
for (led_brightness=0; led_brightness = 255; led_brightness++)
{
ANALOG_WRITE(9, led_brightness);
}
Almost the same as the Arduino version, only letter cases are changed. In order to easily migrate Arduino code to Arduino-Lite, most Arduino-Lite version of the functions in the Arduino come with the all capitalized letters.

1.2 The defects to the Arduino

Slow

The implementation of digitalRead() digitalWrite() and analogWrite() functions in Arduino are very heavy, and less effective. In order to make the numbering pin feature work properly, while invoking IO operating functions, pin numbers need to be converted to the controller register. Let us see into the analogWrite() function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void analogWrite(uint8_t pin, uint8_t val)
{
pinMode(pin, OUTPUT);
if (digitalPinToTimer(pin) == TIMER1A) {
// connect pwm to pin on timer 1, channel A
sbi(TCCR1A, COM1A1);
// set pwm duty
OCR1A = val;
} else if (digitalPinToTimer(pin) == TIMER1B) {
// connect pwm to pin on timer 1, channel B
sbi(TCCR1A, COM1B1);
// set pwm duty
OCR1B = val;
} else if (digitalPinToTimer(pin) == TIMER0A) {
if (val == 0) {
digitalWrite(pin, LOW);
} else {
// connect pwm to pin on timer 0, channel A
sbi(TCCR0A, COM0A1);
// set pwm duty
OCR0A = val;
}
} else if (digitalPinToTimer(pin) == TIMER0B) {
if (val == 0) {
digitalWrite(pin, LOW);
} else {
// connect pwm to pin on timer 0, channel B
sbi(TCCR0A, COM0B1);
// set pwm duty
OCR0B = val;
}
} else if (digitalPinToTimer(pin) == TIMER2A) {
// connect pwm to pin on timer 2, channel A
sbi(TCCR2A, COM2A1);
// set pwm duty
OCR2A = val;
} else if (digitalPinToTimer(pin) == TIMER2B) {
// connect pwm to pin on timer 2, channel B
sbi(TCCR2A, COM2B1);
// set pwm duty
OCR2B = val;
} else if (val < 128)
digitalWrite(pin, LOW);
else
digitalWrite(pin, HIGH);
}
The code is long. If we operate the registers directly, it will be:
1
OCR01 = led_brightness;
The difference between codes makes 10x difference in performance. This makes Arduino not be suitable for efficiency-sensitive products or fields.

The size of the binary

For the same reason, the size of the binary of Arduino are really big. The fading led example is about 2kb compiled with the Arduino library, what is about half of the available rom size of Atmega48/attiny chips. Binaries like this size will not be acceptable in cost-sensitive situations, and even to the hobbyists, large binaries limit the feature of the program.

Only limited AVR models are support, and have some restrictions on external hardwares

Arduino only support Atmega8/Atmega168/Atmega328/Atmega1280 working on 8MHz or 16MHz with external crystal. Some products doesn’t need such high performance chips, might choose Attiny series, atmega48 or atmega88, which is cheaper. In some application, the two frequencies cannot cover the requirement of performance or power consumption. Arduino cannot help in these situations.

1.3 Modifications made by Arduino-Lite

Thanks to the marcos in Arduino-Lite, we keep it simple but providing higher performance and smaller binary size. Almost all core functions in Arduino have their Arduino-lite version, most of which are implemented by marcos. In Arduino-Lite, the conversion from numbering pin to AVR registers are finished in the compiling phase, which is in the runtime in Arduino. Let take the PWM example once more: The equivalent of analogWrite(pin, value) in Arduino-Lite is ANALOG_WRITE(pin, value). Outputing PWM signals to the Pin 9 should be like this:
1
ANALOG_WRITE(9, pwm_value);
This is almost the same as the arduino version, but after macro expension:
1
2
3
4
5
6
#define ANALOG_WRITE( pin, val )  \
do{                          \
PWM_ENABLE(pin);        \
PWM_SET(pin,val);       \
}                            \
while(0)
And expend the PWM_ENALBE and PWM_SET:
1
2
sbi(TCCR1A, COM1A1);
OCR1A = pwm_value;
Compared to the heavy lone Arduino version,Arduino-Lite generates only 2 AVR instructions to fulfill the same requirement. Arduino-Lite also provide reduced interfaces, such as PWM_SET(pin, value) generates only 1 instruction. Let’s compare the binary size of the LED fading example
LED Fading(PWM)
  • Arduino version: 2048 byte
  • Arduino-Lite version: 100byte
In Arduino, ADC pins (PC port) can only operate in analog mode (using analogRead), and cannot be used as digital IO port. In Arduino-Lite, we extended the pin numbers of Arduino, and make adc pins to be operated as digital IOs. The pin definition of AtMegaX8(m48,m88,m168,m328):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ATMEL ATMEGA8 & 168
//
//                  +-\/-+
//            PC6  1|    |28  PC5 (AI 5/*D19)
//      (D 0) PD0  2|    |27  PC4 (AI 4/*D18)
//      (D 1) PD1  3|    |26  PC3 (AI 3/*D17)
//      (D 2) PD2  4|    |25  PC2 (AI 2/*D16)
// PWM+ (D 3) PD3  5|    |24  PC1 (AI 1/*D15)
//      (D 4) PD4  6|    |23  PC0 (AI 0/*D14)
//            VCC  7|    |22  GND
//            GND  8|    |21  AREF
//     *(D20) PB6  9|    |20  AVCC
//     *(D21) PB7 10|    |19  PB5 (D 13)
// PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
// PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
//      (D 7) PD7 13|    |16  PB2 (D 10) PWM
//      (D 8 )PB0 14|    |15  PB1 (D 9) PWM
//                  +----+
We will introduct the detailed guide to install and use Arduino-Lite in following articles. Arduino-Lite, Lightweight AVR library(2)   ElecFreaks - electronic design, electronics components, development platform