This project is to program an AVR microcontroller in a ‘manual’ way. When we normally program a microcontroller we write a program in e.g. C, and then hit transfer program and ‘voila’ the program is now loaded in to the microcontroller and it works – at least sometimes
With manual – we will here try to understand what we actually send (as in bit by bit) to a microcontroller in order to program it. We all now it has to be all 1’s and zero’s – but how and in what sequence.
When buying a microcontroller can it do anything?
Unless you bought the microcontroller with a program loaded, it will be empty – and when powering it up, it will not perform anything. It will look at memory address 0000 for a program instruction– and with nothing here it will just stop.
From the above, it is already clear that it actually do something – like try to execute a program – so it is not a complete ‘dumb’ brick.
Other thing it holds is the ability to understand the instructions provided when we load a program. As an example, it already holds the ability to add numbers – provided we give it the right instructions. The instructions available will be listed on the datasheet of the microcontroller or it might be available as a general instruction sheet for a group (family) of microcontroller.
No matter how we create the program, at the end it needs to be loaded in to the microcontroller as binary code – all zero’s and one’s. No one in their right mind would want to program binary directly, we will always use some kind of higher level tool, like C, C++ etc. and then have a compiler change this in to the level of code needed.
When looking at the AVR instruction set ( http://www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf ), we can see some example instructions and their binary code. This is the instruction set for AVR microcontroller’s, and you should always check if the instruction is available for your particular microcontroller. In the datasheet of the microcontroller there will be a list of those instructions it support.
For this project we are out of our mind and will try to load a small program, having programmed the binary code our self. When we have tried this once, we will see why we would probably never do this again.
Breaking the AVR microcontroller down
For this journey, I am going to use the ATTiny13 from Atmel. Maybe this turns out to be a bad choice, but my thought was that a simple chip might make this easier to figure out – could be famous last words.
Hre is a link to the datasheet for the ATTiny13:http://www.atmel.com/Images/doc2535.pdf. One thing to point out is that the table of content is in the end of the 176 pages – not sure why.
Every vendor of microcontroller’s have their own design, so what I am showing here for the ATTiny13 microcontroller, is generally the same for all AVR chips from Atmel, but other vendors will have other designs. Please take this in to account when reading this.
The microcontroller contains a lot of things, but for now we will look at 3 parts, that are of especially interest when programming the microcontroller:
The pin’s in the microcontroller
where we can store the programmed – Flash memory
where we can store data – SRAM
The internal clock – this control the execution time for instructions
Let’s start looking the PIN’s.
The Attiny13 has 8 pins, and when you look at the microcontroller you will see a little mark or circle in one end – on the above picture you see this at the top of the microcontroller.
One thing that might look confusing is the Pbx and then the number of the pin being something different. The PB is for the Port, and e.g. PB0 is Port 0, where as the 1 – 8 are the actual physical pins on the microcontroller.
If you look at the datasheet you will see the pins will often have more than one designated purpose, that is it can be used for more than one thing. What it is used for depends on your program. A little later we will see that we use some of the pins for programming the microcontroller, and here we give them a different designation.
Memory in the Attiny13
When working with computers, we often think of memory, like hard disk, as being something different from the computer. For a microcontroller we both have the CPU and the memory on the same physical device. If more memory is needed, we can communicate with external memory units, but at least the program will be loaded and stored in the microcontroller.
Flash Memory – 1kB
This is the memory where we will load the program. For the Attiny13 we have 1Kb available for our program. Compared to your computer where we talk about giga or tera-bytes, this is course extremely small.
This is non-volatile storage, and will keep the program also when there is no power to the microcontroller. It is this non-volatile behavior that we use to enable reloading the microcontroller until we are satisfied with the progrsam or when we need to try something new with the microcontroller..
SRAM ( Static RAM) – 160 bytes (64 bytes)
If we look at the datasheet it states that the Attiny13 has 64 bytes of SRAM, but I find that other descriptions where they are stating that all 160 bytes are actually more understandable, the fact that 32 bytes are reserved for general-registers and 64 bytes reserved for standard I/O registers. That leaves 64 bytes for SRAM that can be used by our programs.
Below is breakdown of this memory with the associated memory addresses, I have noted both the hex values and the decimal value of the addresses:
EEPROM (Electrically Erasable and Programmable Read-Only Memory)– 64 bytes
This storage has a couple of disadvantages; compared to SRAM it is slow, and it does have a limit to how many times you are able to write to these addresses before it is likely to fail. In the datasheet you will find that they state that after approximately 100,000 writes this memory might start failing.
100,000 might sounds like a lot, but if we were to write a measurement from a sensor to a specific address once every second, this would be less than 30 hours of sampling before this address might start to fail. In order to extend the life of this, the Attiny has a build in logic where a new value is only written to the address if it is different from what is currently stored – for many applications this would of course prolong the life of the address cell.
This storage is non-volatile, so it does keep it’s data with power off.
The Internal Clock
The Attiny13 has an internal clock that runs up to 10MHz, even though the datasheet states that up to 20 MHz is possible, as long as you ensure voltage to be between 4.5 – 5.5V at any time.
1 clock cycle is the time of one high ‘1’ and one low ‘0’ pulse, and it is not really a clock as we would state it in the regular world, as we cannot precisely assume actual time based on this. The actual speed dependent on things like temperature.
Most AVR instructions can be executed within 1 clock cycle, and we have therefore a direct link between the clock cycle and the number of instructions our program is able to execute within a given time. For most projects the speed is probably not a big issue though.
It should be noted, that it is possible to provide the Attiny13 with an external clock as well. This would the case if we need either a very precise clock-cycle or a clock-cycle that we can not configure the Attiny13 to produce with the internal clock.
In this project, we will actually use this option to control the clock externally when loading the program in to the microcontroller– but we will look at this a little later.
How do we program the microcontroller
Often we talk about how to create the program that will run in the microcontroller, but here we are talking how to get a program in to the microcontroller in the first place.
For this project we will use the SPI (Serial Peripheral Interface) to load the program in to the microcontroller. This option is available for most microcontroller’s and is also used for a microcontroller to communicate with other devices.
In order to to program the microcontroller we only need to use 3 pins:
SCK: clock synchronizes all operations of data exchange
MOSI (master Out Slave In) – data from master to slave
The 4th pin used in the standard SPI is:
MISO (Master Slave Out) – data from slave to master
In order for us to program the microcontroller MISO is not strictly needed, unless wanted to read back data from the microcontroller as part of our load process. This would be a good idea to do if we where building a more solid load program, but for this test project we will not use this feature.
In addition to using the pins for SPI we also need to provide the controller with power and ground.
Understanding the clock (SCK) and the effect
When using the SPI, we control the clock speed manually using the SCK pin. The great think about this design is that we can choose the speed of the clock AND it does not even have to be a constant speed. This is what we mentioned under the internal clock, that we also have the option of supplying the clock from an external source.
One clock cycle is the time it takes for a high level + a low level of the clock – see picture.
From a communication perspective to two interesting parts are the rising edge and the falling edge – the 2 red arrows. The ATTiny13 will read (load) data at the rising edge – so if we want to load a value present on any pin on the microcontroller, we need to have the value present on this pin – BEFORE the clock moves from 0 to 1.
In our case where we want to write a program to the ATTiny13, we treat it as the slave. So the data we need to load should be connected to the MOSI (Master Out Slave In) pin of the microcontroller.
Let’s look at an example:
We want to load a ‘1’ in to memory of the microcontroller, and we will use the MOSI pin for this input. The steps we need to take then is:
Set the MOSI pin to ‘1’
Raise the signal on the SCK pin to ‘1’
That is it – now we have loaded a ‘1’. In order for us to load the next bit, we need to bring the SCK signal down to ‘0’ and then when raising this to ‘1’ again the value of the MOSI pin will now be read. If we had kept the signl on MOSI at ‘1’, then we would have loaded ’11’ in to the microcontroller.
So we only need to do this a few thousands times, and we have the program loaded
Before we do the above, we need to prepare the ATTiny13 for programming. Again from the datasheet we can see how they expect this to be done.
Preparing the ATTiny13 to accept a program.
With the above knowledge, let’s look at the steps for programming the microcontroller. If we look in the datasheet of the ATTiny13 microcontroller we can find the suggested settings (section 17.6.1):
Power up the microcontroller
Set the SCK pin low (0)
Set the RESET pin to high (1) for minimum 2.5 milliseconds
Set the RESET pin to high (0)
Wait a minimum of 20 milliseconds
Send the ‘programming enabling code’ – this code be found in table 17-9 of the datasheet.
After the above, the microcontroller is ready to receive the program.
Before we go to the programming, let’s make sure that we know how to do the above. I think step 1 – 5 are pretty clear, it is just a matter of setting specifics pins to either high or low, and step 5 is just a wait. When we write the code in the Arduino IDE, we will see this again.
Let’s look at step 6 in more detail.
Send the programming enabling code.
From the ATtiny13 data sheet (table 17-9) we see that the code for enabling the microcontroller to accept a program is:
1010 1100 0101 0011 xxxx xxxx xxxx xxxx
Where the x indicate the the value of the bit does not matter – BUT we still have to send something to the microcontroller. I will in this example just use 0’s where I can enter any value.
The 2 pins we need to control for loading data to the microcontroller is SCK and MOSI. As we have seen from the clock signal (SCK signal) the data will be loaded in to the microcontroller when we raise the this to high (‘1’).
So the process we will follow is then:
As you see, it is only the first step that changes – is the bit we want to load.
This is how simple the process really is, after we have loaded all 32 bit’s – we have enabled the microcontroller for programming. After the last bit, it automatically perform the instruction – so there I not a step like ‘Execute’ or similar we need to do after loading the last bit.
We are now ready to load the actual program.
Loading the program is similar to the above process – all instructions are basically a set of 32 bit’s, we just need to find all the instructions and have them available in binary form.
The next step it to construct the program that we will then load using the above process – this we will do in part 2.