Exercise 08 Embedded Programming...

Intro

This week assignment is embedded programming. The exercise required this week is to use as many methodologies to program the MCU boards fabricated. Lesson objective is to familiarize with the workflow when it comes to programming boards.

Few years ago while I was looking for a small cap low cost MCU to replace the Arduino (ATMega328), I have chanced upon MIT High Tech Low Tech, the notion of using Arduino Uno (ATMega328) as the ISP programmer to program ATTiny84/85 has got me hooked URL here http://highlowtech.org/?p=1706 Since the discovery, I have designed and fabricated my own PCB Arduino ISP to program ATTiny85 and I have documented a step by step guide to setup Arduino IDE to do the programming of ATtiny85. That was done in Arduino IDE v1.05, quite outdated by today’s v1.65. nonetheless, the workflow is similar. This workflow is synonymous to programming the ATtiny44 hello board. So out of convenience with the Arduino laying on top of my desk, I have decided to use it as my ISP. At the troubleshooting section, I have outlined the issues faced when programming the ATtiny44 board and some methods used for problem solving.

The following is a list of things done, or work in progress
0. programmed the stuffed ATtiny44 hello with Arduino 1.65 IDE on win8.1
1. programmed the stuffed ATtiny44 hello with GCC on ubuntu14.04
2. programmed the final project MCU board with Arduino 1.65 IDE
3. programmed the final project MCU board with GCC on ubuntu14.04

Read data sheet of ATtiny44

A summary of ATTiny44 data sheet is available here http://www.atmel.com/Images/8006S.pdf
The summary datasheet of ATtiny44 documentation only contains several information that is useful to the product developer that required the use of the main features of the ATtiny44 MCU. Information such as the pinout diagram, overview of microcontroller architecture, summary of the registers, instruction set for assembly language, and packaging information. In depth details are not covered in this summary data sheet. The 238 pages ATTiny44 data sheet gives details such as Port B (PB0:3) and Port A (PA0:7) are bit programmable, bi-directional I/O ports with internal pull-up resistors. PB3 can be used as an I/O pin instead of RESET and this is done by programming a 0 into the RSTDISBL fuse.

Another issue i observed. With modern tools such as Arduino IDE and Arduino UNO that abstract the detail and intricated know-how of a MCU, the end user lost of the background know-how bit by bit at every press of the "download" button on the Arduino IDE. It is good for end users to immerse in the detailed step by step of programming a MCU without MCU.

Read data sheet of ESP8266

A summary of ESP8266 datasheet is available here http://download.arduino.org/products/UNOWIFI/0A-ESP8266-Datasheet-EN-v4.3.pdf
The above ESP8266 summary data sheet provides some useful info, especially for ultra low power application. It was reported the "ESP8266EX consumes about than 60uA in deep sleep mode (with RTC clock still running) and less than 1.0mA (DTIM=3) or less than 0.5mA (DTIM=10) to stay connected to the access point". From the data sheet, the user is informed that the ESP8266 is made with "Tensilica L106 32-bit micro controller (MCU) with The CPU clock speed is 80MHz. It can also reach a maximum value of 160MHz"; which features extra low power consumption and 16-bit RSIC. One of the interesting finding is "Real Time Operation System (RTOS) is enabled". The data sheet also gives details on the GPIO "There are up to 17 GPIO pins. They can be assigned to various functions by the firmware. Each GPIO can be configured with internal pull-up (except XPD_DCDC, which is configured with internal pulldown)". Another interesting finding: GPIO2 and MTMS can be used for I2C, I2C_SCL and I2C_SDA respectively. the clock limitation is also mentioned "Both I2C-Master and I2C-Slave are supported. I2C interface functionality can be realized via software programming, the clock frequency can be up to around 100KHz at most."

Unfortunately, the above data sheet for ESP8266 only describe the SoC itself, and did not address the product e.g ESP01 or ESP12E, the pins to be held at which state during programming mode, and execution mode. The lacking in applicatio notes posed as a steep learning curve for user that wants to use ESP8266 at product level, instead of SoC level. Luckily, there are some documentations available posted by makers or board manufacturers alike. The following 2 URLs describe the product made with ESP8266 SoC.
http://www.esp8266.com/wiki/doku.php?id=esp8266-module-family
http://www.seeedstudio.com/wiki/images/7/7d/ESP-12E_brief_spec.pdf

Setting up Arduino IDE v1.65 to program the ATtiny44

With the introduction of boards manager in Arduino IDE v1.65, adding a non Arduino MCU is a breeze as compared to the earlier steps outlined in the intro section. It is as simple as going to tools, then boards, and lastly boards manager. From boards manager, one could search for ATtiny family of MCU. For the uninitiated, MIT high low tech group has a very well documented guide here The following screenshot describes the config on Arduino IDE v1.65

wiring up of Arduino as ISP and the ATTiny44 hello board

The following picture describe the wiring scheme described in the source code of ArduinoISP

Burning the bootloader and Programming the ATtiny44 with Arduino IDE, and Arduino as ISP

The following screenshots describe the burning of the bootloader to the ATtiny44



The board doesn’t smell like roast chicken during power up and burning of bootloader. After the successful burning of the bootloader, I have used the example code such as blink , fade, and button to test the LED and button on my ATtiny44 board.

The functionality tests are successful with the following diagram describing the LED lighting up with source code of blink, and fade

The original source code is available in Arduino IDE, the only changes done is to change to the pin number8 for LED. Besides the LED and the switch, I have also tested the serial comm of my ATtiny44 board with a sample code of echo downloaded from http://arduinobasics.blogspot.sg/2012/07/arduino-basics-simple-arduino-serial.html.

One thing to note, it is best to have the pin number reference handy when programming the ATtiny44. The high low tech group provide such instance here

http://highlowtech.org/wp-content/uploads/2011/10/ATtiny44-84.png

Burning the bootloader and Programming the ATtiny44 with GCC, and Arduino as ISP

Fab Academy has an excellent tutorial on using the most fundamental tools that exposed all the inner workings of writing program for ATtiny44. Read here for more details. I have referenced neil’s hello.ftdi.44.echo.c and it’s make file hello.ftdi.44.echo.c.make. Unfortunately, the code from the URL mentioned earlier does not work out of the box for me. Partly due to the difference in the wiring of the pins between neil’s ATtiny44 board and mine, and also the ISP used. I have used Arduino as the ISP. The following picture describes it.



I have to make some modifications to the original makefile, due to the lack of Arduino as ISP in one of the parameters to be fed to avrdude. Refer to line #36 onwards at the code below
#makefile command
sudo make -f hello.ftdi.44.echo.c.make program-ardu 

PROJECT=hello.ftdi.44.echo
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-bsd: $(PROJECT).hex
	avrdude -p t44 -c bsd -U flash:w:$(PROJECT).c.hex

program-dasa: $(PROJECT).hex
	avrdude -p t44 -P /dev/ttyUSB0 -c dasa -U flash:w:$(PROJECT).c.hex

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

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

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

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

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

program-ardu: $(PROJECT).hex
	#avrdude -p t44 -P /dev/ttyACM0 -c stk500v1 -b19200  -U flash:w:$(PROJECT).c.hex
	gdb -args avrdude -p t44 -P /dev/ttyACM0 -c stk500v1 -b19200  -U flash:w:$(PROJECT).c.hex
Initially when I used the original echo.c, I could not get any responds on the serial comm. I have tried fiddled with the bps and such, but to no avail. Then I come to realise my TX and RX pins on my hello board is different. Hence I have to change it at the #define

Modifications made Refer to line #37 and #38 onwards at the code below
//
//
// hello.ftdi.44.echo.c
//
// 115200 baud FTDI character echo, with flash string
//
// set lfuse to 0x5E for 20 MHz xtal
//
// Neil Gershenfeld
// 12/8/10
//
// (c) Massachusetts Institute of Technology 2010
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all 
// liability.
//

#include 
#include 
#include 

#define output(directions,pin) (directions |= pin) // set port direction for output
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 8.5 // bit delay for 115200 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define char_delay() _delay_ms(10) // char delay

#define serial_port PORTA
#define serial_direction DDRA
#define serial_pins PINA
#define serial_pin_in (1 << PA1) //PA1 is RX
#define serial_pin_out (1 << PA0)//PA0 is TX

#define max_buffer 25

void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) {
   //
   // read character into rxbyte on pins pin
   //    assumes line driver (inverts bits)
   //
   *rxbyte = 0;
   while (pin_test(*pins,pin))
      //
      // wait for start bit
      //
      ;
   //
   // delay to middle of first data bit
   //
   half_bit_delay();
   bit_delay();
   //
   // unrolled loop to read data bits
   //
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 0);
   else
      *rxbyte |= (0 << 0);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 1);
   else
      *rxbyte |= (0 << 1);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 2);
   else
      *rxbyte |= (0 << 2);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 3);
   else
      *rxbyte |= (0 << 3);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 4);
   else
      *rxbyte |= (0 << 4);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 5);
   else
      *rxbyte |= (0 << 5);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 6);
   else
      *rxbyte |= (0 << 6);
   bit_delay();
   if pin_test(*pins,pin)
      *rxbyte |= (1 << 7);
   else
      *rxbyte |= (0 << 7);
   //
   // wait for stop bit
   //
   bit_delay();
   half_bit_delay();
   }

void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
   //
   // send character in txchar on port pin
   //    assumes line driver (inverts bits)
   //
   // start bit
   //
   clear(*port,pin);
   bit_delay();
   //
   // unrolled loop to write data bits
   //
   if bit_test(txchar,0)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,1)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,2)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,3)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,4)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,5)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,6)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   if bit_test(txchar,7)
      set(*port,pin);
   else
      clear(*port,pin);
   bit_delay();
   //
   // stop bit
   //
   set(*port,pin);
   bit_delay();
   //
   // char delay
   //
   bit_delay();
   }

void put_string(volatile unsigned char *port, unsigned char pin, char *str) {
   //
   // print a null-terminated string
   //
   static int index;
   index = 0;
   do {
      put_char(port, pin, str[index]);
      ++index;
      } while (str[index] != 0);
   }

int main(void) {
   //
   // main
   //
   static char chr;
   static char buffer[max_buffer] = {0};
   static int index;
   //
   // set clock divider to /1
   //
   CLKPR = (1 << CLKPCE);
   CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
   //
   // initialize output pins
   //
   set(serial_port, serial_pin_out);
   output(serial_direction, serial_pin_out);
   //
   // main loop
   //
   index = 0;
   while (1) {
      get_char(&serial_pins, serial_pin_in, &chr);
      put_string(&serial_port, serial_pin_out, "hello.ftdi.44.echo.c: you typed \"");
      buffer[index++] = chr;
      if (index == (max_buffer-1))
         index = 0;
      put_string(&serial_port, serial_pin_out, buffer);
      put_char(&serial_port, serial_pin_out, '\"');
      put_char(&serial_port, serial_pin_out, 10); // new line
      }
   }

	
The following picture describes the programming of the echo C code to ATtiny44 with Arduino as the ISP

The following picture describes the output observed on the serial comm via PUTTY
one thing i notice, in the above putty output, it does not corresponds to the supposedly output as per described in the code. have to troubleshoot further.

One final note, I have used gdb in the makefile, apparently without it, I could not burn the bootloader nor program my ATtiny44. I have inferred this from my week 4 exercise.

Burning the bootloader and Programming the board for final project, with Arduino IDE, and Arduino as ISP

Work in progress. The following picture describes the stuffed board for final project.

troubleshooting

For some apparent unknown reason, when I first burn bootloader with the correct parameters and programming the ATtiny44, both using Arduino as ISP, and the Arduino IDE, it seems to went well without error message. The only funny thing is when the LED pin supposed to be logic high, the LED doesn’t light up, and the measured voltage is 0.4v instead of 5v. It took we quite some time to solve this weird puzzle, trying to isolate whether is a hardware problem or software problem. From hardware point of view, I have done continuity test at different stages of stuffing the board, and my soldering job looks legit. From software point of view, I have used the correct pins, and the simplest code of holding a pin to logic high with digitalwrite(). It still doesn’t work. I hypothesised a few different issues, and tested them, but none lead to a logical closure. Then all of the sudden, I could not burn the bootloader nor program the ATtiny44 with these setup. The verbose mode returns different error message at every time the same code is used to program it. The following pictures describe some of the error messages received.



Out of desperation, I have treated the ATtiny44 board with some Tender Loving Care (TLC) with the hot air gun. Surprisingly, this works.

I have experienced the famous avrdude: stk500_disable() unknown response=0x12, the following picture describes it.

the saving grace is with the use of gdb, the gnu project debugger.

Source files Download

My modified C source code hello.ftdi.44.echo archived in a zip file download here
My modified C source code hello.ftdi.44.echo.c download here
My hex file hello.ftdi.44.echo.c.hex download here
My modified C makefile hello.ftdi.44.echo.c.make-MOD download here
My modified C makefile hello.ftdi.44.echo.out download here
My modified arduino blink example download here
My modified arduino fade example download here
My modified arduino button example download here

Reference

A summary of ATTiny44 data sheet is available here http://www.atmel.com/Images/8006S.pdf
Summary data sheet of ESP8266 http://download.arduino.org/products/UNOWIFI/0A-ESP8266-Datasheet-EN-v4.3.pdf