EmbeddedProgramming

Week Overview
This week we had to familiarize ourselves with a completely new concept, which I had never given much though before the electronic production week. It is the field of embedded programming. It entails programming the internal workings of a processor using assembly code. This can be accomplished using several techniques, a few which will be explored this week.

Programming my hello echo board using an Arduino
This was accomplished in the electronic design week. I used the Arduino as an ISP, where I picked the correct settings and uploaded the bootloader to the chip. I proceeded and programmed my hello echo board to have the LED constantly blink. Once the basic blink script was successful, I programmed the LED to turn on while the button is pressed. Details of how this was exactly accomplished can be found in the

Understanding assembly programming and setting up the Makefile
At first I wanted to get a better grasp on the process of calculating the fuses, writing the program and then using the fabISP to upload said program to the echo hello board. I looked through some of the resources provided and found very helpful in understanding the makefile in detail. The following also provided a summary of what and how the fuses are programmed.
Now that I had a basic idea on how this works, I went on to trying it on my own. I downloaded the makefile template provided for the attiny from the fabacademy resources. As can be seen it contains a lot of unneeded lines and the fuses included do not work with my board's setup.
Having understood the purpose of each line, I edited out all irrelevant lines and left the usbtiny programming lines. The name was edited from usbtiny to fabISP to match my fabISP's name. The last step left for the make file was to calculate and set the fuses.
According to the previously referenced tutorial, I had narrowed down the need to program the fuses, to only programming the LOW fuses in this case. Although there is a calculator included, as per advice of our instructors, it isn't very dependable and would anyway be more benefitial for us to learn how to do it by hand. To fully understand how to program each digit, I had to refer to the Firstly, I set the CKSEL to 0000 since I was using an external clock.

The SUT fuse was next and to be on the safe side, I chose to give the clock the most ammount of time to power on, assigning it a 10.
The CKOUT will not be used in this case, since we are already using an external clock. It will therefore be unprogrammed, given a 1.
Finally the CKDIV8 fusedetermines the initial value of the CLKPS bits. If CKDIV8 is unprogrammed, the CLKPS bits will be reset to
0000
. If CKDIV8 is programmed, CLKPS bits are reset to
0011
, giving a division factor of eight at start up. Any value can be written to the CLKPS bits regardless of the CKDIV8 Fuse setting. So, it will be left to its default programming, as it's not required at this point. This was simply done by assigning it a programmed digit, 0.
Now that I had the binary fuse digits for the LOW fuses, I had to simply rewrite them in hexidecimal digits. Referring to the table on the right, the 00000110 binary digits correspond to a 06.
I replaced the old fuse digits with the newly calculated hex digits in the make file. The makefile seen on the right was ready execute, once the button LED program is complete. I also gave the C program the name, ledblink.
PROJECT=ledblink
SOURCES=$(PROJECT).c
MMCU=attiny44
F_CPU = 20000000

CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)

$(PROJECT).hex: $(PROJECT).out
avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out

$(PROJECT).out: $(SOURCES)
avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)

program-fabISP: $(PROJECT).hex
avrdude -p t44 -P usb -c avrisp2 -U flash:w:$(PROJECT).c.hex

program-fabISP-fuses: $(PROJECT).hex
avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x0A:m

Preparing the button-LED program
The code for programming the behaviour of the board and setting the inputs/outputs was done on the Arduino IDE. I first initialized the required input/output avr library as well as the clock frequency of 20 Mhz. Then I had to set the output and input pins on the chip. This was done using binary, input pins are set to 0 and output pins are set to 1. With the LED connected to pin 11 and th button to pin 6, I used the diagram on the right to locate their pin number in relation to port A. This corresponded to pin 2 for the button and pin 7 for the LED. The binary number that I put together 00000100.
Once the setup was ready, I created a never ending while loop that sends a high signal to the LED pin once the button is pressed and sends a low if the button isn't pressed.

Uploading the program
As mentioned earlier, I will use my fabISP to program the board. In order to do the I must connect the corresponding pins between the two boards as shown in the diagram and image below
Then the makefile and the C code must be saved in the same folder, the makefile without and extentiona and the c file with .c extension.
The next step was to connect the fabISP to the computer using an extension to protect the USB socket of your computer. The FabISP should now show up on the computer. Then next step is to open the directory containing the makefile and the c file. Once in the directory give the make command to create a hex file, then run the make program-fabISP to connect the fuses and program the fuses and the c code onto the board. Unfortunately this was not working on my laptop, so thinking that it may be the laptop's fault, I tried it on the linux machine we have in the lab.
There was still a problem, as can be seen in the log below. After some issue diagnosis, it turns out I had forgotten to remove a jumper cable from my FabISP. Therefore as soon as I removed it the board programmed without any issues.
yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ make
avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=20000000      -I./ -o ledblink.out ledblink.c      
avr-objcopy -O ihex ledblink.out ledblink.c.hex    
avr-size --mcu=attiny44 --format=avr ledblink.out                 
AVR Memory Usage
----------------
Device: attiny44

Program:      64 bytes (1.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ make program-fabISP-fuses
avr-objcopy -O ihex ledblink.out ledblink.c.hex    
avr-size --mcu=attiny44 --format=avr ledblink.out                 
AVR Memory Usage
----------------
Device: attiny44

Program:      64 bytes (1.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x0A:m         


avrdude: error: usbtiny_transmit: error sending control message: Protocol error
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.


avrdude: error: usbtiny_transmit: error sending control message: Protocol error

avrdude done.  Thank you.

makefile:18: recipe for target 'program-fabISP-fuses' failed
make: *** [program-fabISP-fuses] Error 1
yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ make
avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=20000000 -I./ -o ledblink.out ledblink.c
avr-objcopy -O ihex ledblink.out ledblink.c.hex;\
avr-size --mcu=attiny44 --format=avr ledblink.out
AVR Memory Usage
----------------
Device: attiny44

Program:      64 bytes (1.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ make program-fabISP
avr-objcopy -O ihex ledblink.out ledblink.c.hex;\
avr-size --mcu=attiny44 --format=avr ledblink.out
AVR Memory Usage
----------------
Device: attiny44

Program:      64 bytes (1.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


avrdude -p t44 -P usb -c usbtiny -U flash:w:ledblink.c.hex


avrdude: error: usbtiny_transmit: error sending control message: Protocol error
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.


avrdude: error: usbtiny_transmit: error sending control message: Protocol error

avrdude done.  Thank you.

makefile:17: recipe for target 'program-fabISP' failed
make: *** [program-fabISP] Error 1
yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 089: ID 1781:0c9f Multiple Vendors USBtiny
Bus 001 Device 004: ID 17ef:608c Lenovo 
Bus 001 Device 003: ID 17ef:608d Lenovo 
Bus 001 Device 002: ID 8087:0a2a Intel Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ make
avr-objcopy -O ihex ledblink.out ledblink.c.hex;\
avr-size --mcu=attiny44 --format=avr ledblink.out
AVR Memory Usage
----------------
Device: attiny44

Program:      64 bytes (1.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ make program-fabISP
avr-objcopy -O ihex ledblink.out ledblink.c.hex;\
avr-size --mcu=attiny44 --format=avr ledblink.out
AVR Memory Usage
----------------
Device: attiny44

Program:      64 bytes (1.6% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


avrdude -p t44 -P usb -c usbtiny -U flash:w:ledblink.c.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9207 (probably t44)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "ledblink.c.hex"
avrdude: input file ledblink.c.hex auto detected as Intel Hex
avrdude: writing flash (64 bytes):

Writing | ################################################## | 100% 0.06s

avrdude: 64 bytes of flash written
avrdude: verifying flash memory against ledblink.c.hex:
avrdude: load data flash data from input file ledblink.c.hex:
avrdude: input file ledblink.c.hex auto detected as Intel Hex
avrdude: input file ledblink.c.hex contains 64 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.07s

avrdude: verifying ...
avrdude: 64 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:DF, L:62)

avrdude done.  Thank you.

yazan@yazan-ThinkCentre-M710q:~/Desktop/tarek$ 


Attempting a more complex blinking program
After completing the test codes, I wanted to take the program a step further and introduce a changing feedback output. To do that I linked the milliseconds delay integer which is divided by a factor of 1.5 everytime the button is pressed, to reset the blinking simply press the onboard reset button. The code is shown on the right and includes a delay variable representing the milliseconds and an if statement which is activated if the button is pressed. The result of the if loop is the integer decreasing by a factor of 1.5, as mentioned earlier. Outside of the if statement is a neverending while statement which includes a blinking code, where the on and off commands are seperated by a delay dependant on the delay integer. The result was a blinking light that blinked faster everytime the button was pressed. The video below demonstrates this behaviour.
#include <avr/io.h> //initialized avr input/output library
#include <util/delay.h> //initialized delay library required for the delay function

#define F_CPU20000UL //define clock processing
#define LED PORTA //Define LED port
#define Button PA7 //Define button port

int delaynum=2500; //delay variable

int main (void)
{
  DDRA = 0b00000100;
  
    while(1){
      if (Button==1)
      {
        delaynum= delaynum/1.5;
        }
        
        LED = 0b00000100;
         _delay_ms(delaynum);
         LED = 0b00000000;
          _delay_ms(delaynum);
      }
}


What I'd like to learn
After completing this week, I have a better understanding of what embedded programming is. However, I wish to practice this skill further and try it with different input and output devices, as well as communicating to other modules via serial or I2C. Embedded programming is a world that I've never dealt with directly, for fear of its complexity, but is now more approachable.

Files
Please find all the files required, if you feel like making your own:
File Link
Makefile
Simple C code
Complexified C code