Fletch's Fab Academy 2014 Blog
08. Embedded Programming
This weeks task was to read and understand the datasheet for the
ATTiny44 microcontroller on our 'Hello World' boards that we made
the other week and then to program the board to do something
interesting using as many languages and programming anvironments as
possible. My background covers a lot of embedded programming
and I've used ARM and PIC microcontrollers before for lots of
comercial projects. So, rather than try to use as many
languages as possible I decided to change my task slightly and
improve my understanding of what is to me a new microcontroller
family by trying to flex as many of the features of the ATTiny as
possible.
08.01 Board Definition
Before starting I needed to know the definition / IO pin usage of
what was actually on my 'Hello World' board as follows:
- PA0: Tx (labeled from the point of view of the PC talking to
the board, actually data into ATTiny)
- PA1: Rx (labeled from the point of view of the PC talking to
the board, actually data out of ATTiny)
- PA7: Switch input (Switch connects to GND, will need to turn
on internal pull up)
- PB2: LED output (LED is connected to VCC via current limit,
set PB2 low to turn on LED)
08.02 Software Tool Chain
I chose to use 'Crosspack AVR' on the Mac as my gcc tool
chain. I aslo already have XCode installed and as Crosspack
creates blank XCode project templates I decided to use XCode as my
developement IDE.
To create a new project in your developement folder type:
avr-project projectname from a terminal window. This
will create a blank project template with a main.c and a
makefile.
Next you will need to edit the makefile to set the DEVICE, CLOCK,
FUSES and PROGRAMMER correctly as follows:
DEVICE = attiny44
CLOCK = 20000000
PROGRAMMER = -c usbtiny
OBJECTS = main.o
FUSES = -U hfuse:w:0xdf:m -U
lfuse:w:0xff:m -U efuse:w:0xff:m
Then just fill main.c with code, glorious, code...
I may revert to Textmate or Eclipse as an IDE as I'm not completely
happy with some of XCode's features.
08.03 Initial Blink Test
I actually performed this test the other week after building the
board as I wanted to know that it worked. The code (here) blinks the LED
until the switch is pressed, at which point it keeps the LED
on. The code's not pretty but it was a quick and dirty test to
show that:
- My tool chain worked
- My basic understanding of the ATTiny IO port programming was
OK
- My FABISP worked
- My Hello World board layout was what I expected
- My Hello World board had been manufactured OK
The one thing that it didn't test was the serial port.
08.04 Basic Serial Port Test
So the next thing I wanted to check was that the serial port worked
OK. For this I simply used the code that Neil linked from this
weeks class page (non-irq
and irq
based). Initially this didn't work, I could send
characters but not receive them. I tested another students
Hello World board and that was OK. On inspection of my board I
discovered that the 'Tx' pin on the ATTiny wasn't quite soldered
down correctly. A quick re-heat with the soldering iron and my
board worked OK.
On inspection of Neils IRQ based serial code I wasn't happy with it
as it's not truly IRQ based. It uses an IRQ to detect he start
of an received character, but then the actual reception and
transmission processes are blocking. Serial data tx/rx (even
at 115200 baud) is a slow process in terms of the number of CPU
instructions that could be run whilst a single character is being
sent on the serial line. So this blocking actually stalls the
CPU for a significant time. This is OK for a simple test, but
not very practical if any 'real time' work needs to be done.
08.05 Test Signature Bytes and EEPROM
Now that I had working serial communications I extended theh test
silghtly in two ways. Firstly to read the device signature
bytes so that I could see that the device actually reported itself
as an ATTiny44a.
Then secondly, to read and write the EEPROM on the device. I
did a simple test that performed the following actions each time the
device booted up:
- Read address 0 from EEPROM and print it out via serial port.
- Increment value by 1 and write back to EEPROM address 0.
This gave me a very simple incrementing 'boot count' telling me how
many times the device had been powered on. For a real
commercial product a there are two issues with this:
- The EEPROM value is never initialised, I start counting from
what ever value is in the EEPROM at the end of the manufacturing
process. Appears to be 0xFF.
- There is no corruption check. A CRC or checksum needs to
be added. This would also allow for initialisation of a
new device as it would fail the CRC.
Code for the above tests is here.
08.06 Improved Serial Code
I decided that I'd like to have a proper IRQ base impementation of a
software UART. I thought that someone will already have
implemented it, and when I looked around I found this application
note from Atmel that describes exactly what I want,
AVR304: Half Duplex Interrupt Driven Software UART
AVR304 Half Duplex
Interrupt Driven Software UART. However once I
downloaded the code and inspected it the existing examples only
support the ATMega range of microcontrollers. The code is also
written for Atmel Studio which has slightly different sets of
compiler directives for things specific to the Atmel
processors. So I decided to port the code over the the
ATTiny44 and the gcc toolchain.
- Read the application note and it's associated code to
understand what's going on.
- Read the ATMega48 and the ATTiny44 data sheets in tandem to
understand any differences in the parts of the microcontroller
that are used.
- Read the AVR-LibC
and Crosspack User Manuals to understand the differences in the
compiler directives.
The code in AVR304 requires one 8bit timer (Timer0) and one external
interrupt (INT0). These resources exist on the ATTiny44,
however our serial port is wired to the wrong pins on the
chip! We need the serial data in (Tx) to be connected to the
INT0 pin in order to be able to use it's edge detect based IRQ
functionality correctly, the level change IRQ functionality of the
PCINTx pins isn't good enough as we can't specify IRQ's based on
only rising or falling edges. It could be fudged together by
checking the pin state after the IRQ is generated, but as the
correct pins are actually available I decided to re-work my Hello
World board slightly. I decided to modify the board definition
as follows:
- PA0: Tx (labeled from the point of view of the PC talking to
the board, actually data into ATTiny), not used any more but
leave Tx connected here as it has no effect.
- PB2: Tx, this is the INT0 pin so I've connected Tx here also.
- PA1: Rx (labeled from the point of view of the PC talking to
the board, actually data out of ATTiny)
- PA7: Switch input (Switch connects to GND, will need to turn
on internal pull up)
- PA3: LED output (LED is connected to VCC via current limit,
set PB2 low to turn on LED)
- I've disconnected the LED from PB2 by cutting the
track.
- I've re-connected the LED to PA3 with a wire llink.
- Then I've connected PA0 to PB2 to route the Tx signal to both
pins, PA0 isn't needed any longer but it was easier to leave it
connected.
I used the legs of old through hole resistors for the re-work.
After this re-work I re-tested both my old serial code (with changes
for new pins) and re-tested the Blink test code. Both worked
OK.
I've ported most of the serial code and in essence it works
OK. Some tweeks are needed based on the actual processor
resources available. Code is here.
08.0X Game
I'd like to push things to see if I can actually write a game using
just one button and one LED. I think that either of the
following should be possible:
- A 'Simple Simon' type game where the device blinks and LED in
a rhythmic pattern that the user has to remember and then
repeat.
- A reaction timer game where the user presses the button as
fast as possible when the LED comes on.
For both of the above the serial port can be used to print out high
scores stored in EEPROM. A simple menu system could also be
implemented on the serial port allowing the user to select which
game they want to play.
ToDo:
Re draw Eagle schematic to reflect re-works on board.