Code, better
1. Tasks
1.1. Task 1
-
Load the original Arduino
.ino
version of ShortSquawker onto an ATtiny85 and demonstrate it squawking as demonstrated during class time.
The ISP programmer interferes with the user pushbutton’s pin. Disconnect that pin from the programmer after programming or else the pin will be read as low constantly, as if the user is holding the button down all the time. An alternate solution for development is to disable the state machine that handles the input button by commenting-out attiny_shortsquawker.ino line 487. This, of course, disables the user button feature. |
1.2. Task 2
-
Port the code to C and demonstrate that it still operates the same.
Make a new folder to hold the C version, copy the .ino
file into it, then change the file name such that it ends in``.c`; perhaps to main.c
.
Figure out the process to compile this code and end up with a .hex
file suitable for programming with avrdude
using the tools included with the WinAVR package.
Modify the code as necessary to build with the following requirements:
-
Use
avr-gcc
option-std=c99
to use the 1999 C standard.[1] -
Turn on all warnings, and trigger none with your code:
-
-Wall -Wextra -Werror
-
Along the way, create a Makefile to orchestrate those commands and dependencies for building the firmware.
You should be able to begin with the .c
file and Makefile
(and perhaps other source files), run make upload
from a command window, and have the system compile, link, and upload the .hex
to your chip using avrdude
.
1.3. Task 3
-
Rewrite function
void debug_value(uint16_t)
in assembly to ensure that each bit interval is exactly the same duration.
That function’s purpose is to barf out the value of a 16-bit number out of a pin similar to a UART signal. It first outputs a 0-1-0 pulse, then the variable’s bits lsb first, then another 0-1-0 pulse.
1.4. Task 4
Improve the code by e.g. making data types more consistent or other cleanup.
Fix the wave_triangle()
function to actually create a triangle shape.
When the input is over-limit, turn the timer off instead of just pausing the output waveform generation.
Add a feature to power off the system when there has been no user activity after some interval.
2. Example avr-gcc project
Copy this main.c
and one of the Makefile
examples to a folder.
Then use the WinAVR command window to run make
to generate .hex
and .lst
file outputs.
main.c
— Toggle a pin example#include <avr/io.h> // Register names
#include <util/delay_basic.h> // for _delay_loop_2()
/*** Configuration constants ***/
#define LED_PIN PB3
int main(void)
{
// <avr/sfr_defs.h> defines the macro _BV() as
// #define _BV(bit) (1 << (bit))
// Use PB3 as the output
DDRB |= _BV(LED_PIN);
while (1) {
// toggle pin and do it again
PORTB ^= _BV(LED_PIN);
// 65536 iterations, 4 clocks each + call overhead
_delay_loop_2(0);
}
}
Makefile
— minimal example# minimal Makefile
# no variables or other features except for command line continuations
.PHONY: default
default: main.hex main.lst
main.o: main.c
avr-gcc -c -mmcu=attiny85 -std=gnu99 -g -Os -flto -Wall -Wextra \
-DF_CPU=8000000 main.c
main.elf: main.o
avr-gcc -mmcu=attiny85 -g -Os -flto -Wall -Wextra \
-fuse-linker-plugin -Wl,--gc-sections -o main.elf main.o
main.hex: main.elf
avr-objcopy -O ihex -R .eeprom main.elf main.hex
main.lst: main.elf
avr-objdump --disassemble --source --line-numbers --demangle \
main.elf > main.lst
.PHONY: clean
clean:
rm main.o main.elf main.hex main.lst
Makefile
— alternate example with more featuresMCU=attiny85
# Compiler options (for C language)
COMPILE_C_OPTS=
COMPILE_C_OPTS+=-c
COMPILE_C_OPTS+=-mmcu=$(MCU)
COMPILE_C_OPTS+=-std=gnu11
COMPILE_C_OPTS+=-g
COMPILE_C_OPTS+=-Os
COMPILE_C_OPTS+=-flto
COMPILE_C_OPTS+=-Wall -Wextra
COMPILE_C_OPTS+=-DF_CPU=8000000 # *** must match the fuse settings!
# Linker options
LINK_OPTS=
LINK_OPTS+=-mmcu=$(MCU)
LINK_OPTS+=-g
LINK_OPTS+=-Os
LINK_OPTS+=-flto
LINK_OPTS+=-Wall -Wextra
LINK_OPTS+=-fuse-linker-plugin
LINK_OPTS+=-Wl,--gc-sections
# HEX output options
HEX_OPTS=
HEX_OPTS+=-O ihex
HEX_OPTS+=-R .eeprom
# Listing output options
LST_OPTS=
LST_OPTS+=--disassemble
LST_OPTS+=--source
LST_OPTS+=--line-numbers
LST_OPTS+=--demangle
# The first target is the default if no target was specified.
.PHONY: default
default: main.hex main.lst
# How to compile the .c and get the .o object file.
main.o: main.c
avr-gcc $(COMPILE_C_OPTS) main.c
# Link the objects together to make a single ELF binary
# There may be more than one for some projects.
main.elf: main.o
avr-gcc $(LINK_OPTS) -o main.elf main.o
# Generate HEX file for programming the chip
main.hex: main.elf
avr-objcopy $(HEX_OPTS) main.elf main.hex
# Dump the listing file so we can inspect the generated assembly.
# No line continuations just because.
main.lst: main.elf
avr-objdump $(LST_OPTS) main.elf > main.lst
.PHONY: clean
clean:
@-rm main.o main.elf main.hex main.lst
3. References
The zip archive has been updated to …valpo2.zip .
|
3.1. Makefile tips
See how make
is interpreting the rules by adding the --debug=v
option:
make --debug=v
When using backslash "\" for line continuation, the "\" MUST be the LAST character on that line. NO spaces or comments.
The continued lines also begin with a Tab character and then four spaces for a nice (optional) indent, like:
<Tab><sp><sp><sp><sp>command
The -g
compile/link option adds extra information to the output object files.
That is how avr-objdump
gets the source code folded into the .lst
output.
The -flto
option is not available in our WinAVR Portable version of AVR-GCC.
The first target is the default if no target was specified.
Build all output files, which are the "leaves" of the dependency graph.
The .PHONY:
target tells make that this is not a real file.
This makes a difference if there ever is a file that is named default
.
Plus, it is good practice to tell the tool (and the next person) that you truly want this target’s rule to run every time.