YADU SHARON
BACK


Embedded Programming



The assignment for this week is to read the datasheet of a board and program it do something. I am from electronics background and I am familiar with AVR, Arduino , Raspberry Pi etc. The board i made in the electronics design week is echo hello-world board with ATtiny 44. Actually I am not very much familiar with tiny44, I used to use ATmega8 and ATmega16 or ATmega32 for normal purpose(only those chips where available here in the local market). So I want to start from the datasheet.

Here is the datasheet of ATtiny44

There are many programming languages like C, aurduino, assembly etc, which can be chosen according to the convenience. According to me I prefer C. I guess majority will be using the Arduino since it is very simple. But if you are using arduino you wont be come to know whats happening inside (my view point).

So lets start with C. As the editor there are many editors available. But for me Atmel Studio (AVR studio) is the best. But there is no version fot MAC and Linux , it is only for Windows. For linux users we can use Eclips with AVR-gcc plug in.

  • Atmel Studio




  • Atmel studio is the IDE developed by Atmel for their chips. So everything related to AVR chips are included in the atmel studio. Their predicion during programming is very good. You can download it here.

    For starting a project, the steps are :
  • Select New project
  • Select GCC C Executable Project (Also givr the name and location)
  • Select the chip
  • Program
  • Compile


  • This is the way we should follow. Once you compile, we will get the hex file in the project folder. (The location is given already)

    Hello world!

    Lets start with an LED blinking hello world program. At present the echo hello world board i made has two leds ,a switch and a 20MHz resonator connected. Since the fuse bits are not set it is using the internal clock. It has a clock speed of 8MHz maximum but by default CKDIV8 will be enabled , so the clock will be 8MHz/8 = 1 MHz . CKDIV8 is a clock prescaler used to change the clock speed. Prescaler is used to scale the clock speed by some values. Take this case, the internal clock for ATTiny44 is 8MHz but if we want the clock as 1MHz then we can prescle it by 8 to get the desired clock.

    Lets start coding, first see the ATTiny44 pin outs and the ports.



    This chip has two ports , PORT A and PORT B. Port A has 8 pins and Port B has 4 pins. All these pins are general input output pins. In my connection leds are connected to PIN 5 and 6 (PB2 and PB7) and switch is connected to PIN 10 (PA3).



    For the "led blink" we are not taking any inputs but we have to assign the corresponding pins as out puts. For setting a pin or a port as input or output, we use the command DDR. For setting the port b as output
    DDRB = 0xFF
    0x represents the hexadecimal. 0xFF means 11111111 in binary. Here 1 represents the output and 0 as input. Here PORT B has only 4 pins so 0xF is enough. For easy understanding we can write it in binary format also like . DDRB =0b1111 . Now if we want to assign the 0th pin as out put and all the other pin of port B as input
    DDRB = 0b0001  // PB0 is output and PB3-1 is input
    See the code for blinking LEDs connected in PB2 and PA7.
    
        
        
    #define F_CPU 1000000           // Defining the clock speed as 1MHz
    #include <avr/io.h>             // Importing the avr/io library (as stdio.h in the normal C)
    #include <util/delay.h>         // Importing library for  delay (For blinking LEDs we need delay)
    
    
    int main(void)
    {
    	
    	
    	DDRA = 0xFF;       //Set PORT A as output
    	DDRB = 0xF;        //Set PORT B as output  
    	
        while(1)
        {
    		
    		
    		PORTA|=(0b10000000);      //Make PA7 high
    		PORTB|= (0b0100);         // Make PB2 high
    		_delay_ms(1000);          // delay of 1 second
    		PORTB=(0xFF);             // Make all pins in port B low    
    		PORTA=(0x0F);            // Make all pins in port A low   
    		_delay_ms(1000);         // delay of 1 second
    		
    				
    	}
    }
         
        
    Here I used PORTA |=(0b10000000). This means PORTA =(PORTA || (0b10000000)). Here the 7the digit of the port a will become 1 and all other pins will remain the same. This is because if we boolean or something with 1 the result will be 1 and if we boolear or something with 0 the result will be the same thing.

    Next I will show how take an input -how to use the switch-. I have written a program to light the led when the switch is pressed.

        
        
     /* LED.c
     *
     * Created: 23-03-2016 23:58:32
     *  Author: YADU SHARON
     */ 
    
    
    #include <avr/io.h>
    
    
    int main(void)
    {
    	
    	DDRA= 0b11110111;	// PA3 as input and all other pin as output	
    	DDRB= 0xF;			// PORTB as output
    	PORTA|=(0b00001000);   // Pulling up the PA3 to which switch is connected
        
        while(1)
        {
    		if (!(PINA & (1<<3)))
    		{
    			PORTA|=(1<<7);
    			PORTB=0xf;
    		} 
    		else
    		{
    			PORTA&=(0x0F);
    			PORTB &=(0x0);
    		}
             
        }
    }
          
        




    If you have some confusion with << operator (left shift) please refer here

    Here is the C file and hex file

    Using the external oscillator

    If we want to use an external oscillator or resonator, just soldering it to the corresponding pins wont do anything but we have to tell the chip that we want to use it. We have already connected the resonator but still we were using the internal oscillator. In order to move to external we have to make some changes in the fuse bits. We have alreay programed the fuse bits and used the external oscillator during the fab isp week itself but very few people would be known of how the fuse byte are selected. Here I will explain it. For that we have to look in to the datasheet.

    See the fuse byte registry (page no 160)


    When we look into the table it is clear that Fuse High Byte doesn't contain any element related to oscillator or clock. So lets keep it unchanged.
    Lets look in to Fuse Low Byte.

    CKDIV8 - This is a clock prescaler. If it is programmed the frequency will be prescaled by a division factor of 8. So if the clock frequency is 20MHz the resulting clock frequency would be 20/8 MHz. So if we want the clock frequency as 20MHz then this bit should be unprogramed. Look in to the table, 0 corresponds to "programmed". To unprogram it it should be 1. So we got the 7th bit of Fuse Low Byte.



    CKOUT -The device can output the system clock on the CKOUT pin. To enable the output, the CKOUT fuse has to be programmed. This mode is suitable when the chip clock is used to drive other circuits on the system. At present we dont want it. So let it be 1.

    CKSEL3:1 - This bits are selected according to the resonator/oscillator we are selecting.



    Here we are using the 20MHz resonator so the value is 111.

    CKSEL, SUT1:0 - For selecting these bits please refer the table.



    Since we are using the resonator , not the crystal the CKSEL0 is 0. For SUT values we should know about slow and fast rising power and about BOD. For that please refer this forum. That page is good for clearing your doubts.
    Anyway I have selected the CKSEL0,SUT1,SUT0 bits as 001.

    So we got all the bits of the Fuse Low Byte.
    
    CKDIV8      1
    CKOUT       1
    SUT1        0
    SUT0        1
    CKSEL3      1
    CKSEL2      1
    CKSEL1      1
    CKSEL0      0
    
    
    Fuse Low Bye    :   1101 1110   
                        D    E
    
    
    
    So the fuse low byte is DE. The high byte we need not change, anyway it is DF by default.Now you can program the fuse using avr dude or which software u r using. If it is avr dude the command is
    
    AVRDUDE -c usbtiny -p attiny44 -U lfuse:w:DE:m
    
    
    


    Now the clock is changed. So the F_CPU is to be defined as 20MHz. Lets try the same led blinking program again.

    
    
        
    #define F_CPU 20000000           // Defining the clock speed as 20MHz
    #include <avr/io.h>             // Importing the avr/io library (as stdio.h in the normal C)
    #include <util/delay.h>         // Importing library for  delay (For blinking LEDs we need delay)
    
    
    int main(void)
    {
    	
    	
    	DDRA = 0xFF;       //Set PORT A as output
    	DDRB = 0xF;        //Set PORT B as output  
    	
        while(1)
        {
    		
    		
    		PORTA|=(0b10000000);      //Make PA7 high
    		PORTB|= (0b0100);         // Make PB2 high
    		_delay_ms(1000);          // delay of 1 second
    		PORTB=(0xFF);             // Make all pins in port B low    
    		PORTA=(0x0F);            // Make all pins in port A low   
    		_delay_ms(1000);         // delay of 1 second
    		
    				
    	}
    }
    
    

    Assembly programming

    the best arguement for why assembly is " while you live in France you are able to get through by speaking English, but you will never feel at home then, and life remains complicated". I got this from a nice and helpfull tutorial. For those who are familiar with C, the assembly is comparitevely simple. As the first step we need the following pdfs

  • AVR 8 bit instruction set
  • AVR Assembler User Guide
  • AVR ASM Tutorial


  • Withou the instruction set it id very difficult to ptogram.

    Setting the environment:
    I use gavrasm to compile and make the hex file from the .asm file. Download it and move to /usr/local/bin: so that you can use it from anywhere. Once you get the .hex file we can burn the chip with the avr dude. The steps are:

  • Open an editor, (eg: nano, gedit) write the code and save it as .asm file (eg:file.asm)
  • Make hex using gavrasm.Suppose we have file.asm as the assembly code the the command is: gavrasm file.asm
  • Burn the chip using avr dude. The command for writing file.hex is: avrdude -c usbtiny -p attiny44 -U flash:w:file.hex


  • Hello world!

    With the same board i used before, lets try some assembly codes. Here is the code for lighting an led which is connected to PORTA7
        
        .device attiny44
        .org 0
        
        sbi DDRA,7      ;make the PA7 as output
        main:
        sbi PORTA,7     ; make the PA7 high    
        rjmp main       ; loop to the main
        
        
    Next I want to try the code to light the led when switch is pressed. I have tried this code in C and now i am writing the code in assembly and lets compare the size of the hex files.
    
    ;led connected to porta 7
    ;switch connected to porta 3
    ;switch work in active low mode
    
    
    .device attiny44
    .org 0
    
    sbi DDRA,7		;set the 7th bit of DDRA, means made the 7th bit as output
    cbi DDRA,3		;set 3rd bit as input
    sbi PORTA,3		; internally pulled up the input bit
    
    main:			;label the main loop
    
    SBIC PINA,3		; skip the next line if the 3rd bit (input) is low
    cbi PORTA,7		; clear the 7th bit(output pin), means digital low at output pn
    SBIC PINA,3		;skip if the 3rd bit is low
    RJMP main		;jump to main 
    sbi PORTA,7		;set the 3rd bit ,means digital high at output pin
    
    RJMP main		;jump to main
    

    Here is the asm file and hex file

    Now lets compare the size of the hex file when it is written in c and in assembly.