Getting started with the ATmega328p

Wat is Arduino?

  • Hardware Boards
  • Embedded Software
  • Ontwikkelingsomgeving
  • Rapid Prototyping

Voor wie is de arduino gemaakt?

Niet voor ons

Is het Arduino platform voldoende?

Nee

Wat is Arduino niet

  • Efficiënt
  • Licht Gewicht
  • Onthullend
  • Performant
  • Programmeertaal

Praktisch Voorbeeld: Memory Usage

Using the Arduinio libraries


#include <Arduino.h>

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
    digitalWrite(LED_BUILTIN, HIGH);
    delay(1000);
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
}
    

Compiled size: 1034 bytes (3.2%)

Without the Arduino library


#include <avr/io.>
#include <util/delay.h>

int main(void)
{
    DDRB = 1 << 5;
    while (1)
    {
        _delay_ms(500);
        PORTB ^= 1 << 5;
    }
  return 0;
}
    

Compiled size: 158 bytes (0.5%)

Praktisch Voorbeeld: Efficiëntie

Snelheid digitalWrite vs bitflip

Arduino is geen taal

  • Arduino is C/C++
  • Het Arduino software framework is gebaseerd op wiring
  • .ino zijn "wannabe" .cpp files

main.cpp

Blink

Om een programma te generen voor een Arduino board is er nog heel wat achterliggend proces nodig. Het framework verstop dit voor ons, zodat we moeilijk een beeld kunnen schetsen van de werking.

Is Arduino geschikt voor ons?

Ja

Maar ...

A great engineer will do for a quarter what a mediocre (at best) engineer takes a dollar to do.

De kostprijs van hardware

Arduino Uno

Kostprijs ≈ 25 euro

Standalone ATmega328p

Kostprijs ≈ 2.5 euro
Dit is geen grondige analyse

Wat zijn de voordelen van het Arduino platform

  • Out of the box features
  • Snel werkend prototype
  • Programmeren via USB
  • Bootloader

Afkicken van Arduino

  • Welke microcontroller gaan we kiezen?
  • Hoe gaan we dat aanpakken?
    • Werking microcontrollers in het algemeen
    • Tooling
    • Bit Manipulatie
    • Datasheet als handboek

We kiezen voor de microcontroller...

ATmega328p

Microcontroller

  • "Standalone"
    • Heeft nog enkele randcomponenten nodig
    • YABBAS
  • Meer dan rekenkundige bewerkingen
  • Afmetingen 8mm x 35mm

Bouwstenen Microcontroller

CPU
  • ALU
  • Register File
  • Program Counter
  • Stack Pointer
  • Status & Control

Bouwstenen Microcontroller

Analoge IO
  • ADC
  • Comperator
  • Kwantiseren van data
Digitale IO
  • HIGH
  • LOW

Bouwstenen Microcontroller

Timer / Counter
  • 2 - 3 Counter
  • Timestamping
  • Event Counters
  • Interval Metingen

Bouwstenen Microcontroller

Interrupt Controller
  • Onderbreken van het programma
  • Speciale hardware interrupts
  • Intern of Extern
Memory
  • Program / Data Memory
  • DMA
  • Memory Types

Bouwstenen Microcontroller

Seriële Interfaces
  • UART
  • I2C
  • SPI
  • ...

Hoe gaan we dit juist aanpakken

Een microcontroller is een digitaal systeem

We moeten dus op de juiste plek de eentjes en de nulletjes correct zetten

Eerst kijken naar de geheugenwerking op de ATMega328p

Geheugen Types

De in het rood omkaderd zitten in de ATMega328p

AVR Geheugen Map

  • Sketch - Flash
  • Variablen - SRAM
  • EEPROM - Alleen maar wanneer aangesproken

General / Special Function Register

  • GPR
    • General Purpose Register
    • Opslagen van willekeurige data
    • Meer info hoofdstuk 11 datasheet
  • SFR
    • Special Function Register
    • Vaste Locatie in het geheugen voor een specifieke functie
    • In dit geheugen zit de data/configuratie voor onze bouwstenen

General Register File

  • Werkgeheugen processor
  • Snelste memory
  • Index register
  • CPU Instructies worden op data vanuit de register file toegepast

Intermezzo

Instructieset wat is dat?

Central Processing Unit

  • ALU
  • Register File
  • Program Counter
  • Stack Pointer
  • Status & Control

Wordt aangestuurd mbv een instructieset

Instruction Set

Mnemonics & Opcodes

Opcodes
  • Operation Code
  • Bytecode dat de CPU kan interpreteren
Mnemonics
  • Ezelsbruggetje voor de opcode
  • Human Readable

ADD | ADC | ADIW | SUB | SUBI | JMP | AND | OR

Wat voor taal hebben we nu beschreven?

Assembly

Instructie Voorbeeld

Instruction Types

  • Arithmetic
  • Branch
  • Data

Instruction Types

  • Bit
  • Controle

High Level To Machine Code

Terug naar

GENERAL / SPECIAL FUNCTION REGISTER

Special Function Register

Zie Register Summary in datasheet

Uitgaande van het Special Function Register moeten we effectief
de eentjes en de nulletjes tot op bit niveau correct zetten

Om dit te kunnen uitvoeren hebben we

Tooling

nodig

Tooling

PlatformIO

Alternatief voor de Arduino IDE
  • Haalt wat van de abstractie van Arduino weg
  • Krachtigere IDE
  • Volgende labos gaan we deze gebruiken
  • Plugin voor verschillende tekst editors
    • Atom
    • Visual Studio Code

Tooling

Toolchain

AVR GCC
  • Arduino / PlatformIO installeren de toolchain achter de schermen
  • We gaan deze niet manueel configuren
  • Deze moet wel gekend zijn.

Tooling

Toolchain

AVR Lib C

  • Header files
    • Beschrijving van function calls met paramameters en mogelijke return waardes
  • Gecompileerde libraries
    • .a Files op Linux
    • .lib files op Windows
  • Source Code is hier te vinden

  ├── include
  │   ├── alloca.h
  │   ├── assert.h
  │   ├── avr
  │   │   ├── boot.h
  │   │   ├── builtins.h
  │   │   ├── common.h
  │   │   ├── cpufunc.h
  │   │   ├── crc16.h
  │   │   ├── delay.h
  │   │   ├── eeprom.h
  │   │   ├── fuse.h
  │   │   ├── interrupt.h
  │   │   ├── io1200.h
  │   │   ├── io2313.h
  │   │   ├── iom328p.h
  │   │   ├── ...
  │   │   ├── lock.h
  │   │   ├── parity.h
  │   │   ├── pgmspace.h
  │   │   ├── portpins.h
  │   │   ├── power.h
  │   │   ├── sfr_defs.h
  │   │   ├── signal.h
  │   │   ├── signature.h
  │   │   ├── sleep.h
  │   │   ├── version.h
  │   │   ├── wdt.h
  │   │   └── xmega.h
  │   ├── compat
  │   │   ├── deprecated.h
  │   │   ├── ina90.h
  │   │   └── twi.h
  │   ├── ctype.h
  │   ├── errno.h
  │   ├── fcntl.h
  │   ├── inttypes.h
  │   ├── locale.h
  │   ├── math.h
  │   ├── setjmp.h
  │   ├── signal.h
  │   ├── stdfix-avrlibc.h
  │   ├── stdint.h
  │   ├── stdio.h
  │   ├── stdlib.h
  │   ├── string.h
  │   ├── sys
  │   │   └── types.h
  │   ├── time.h
  │   ├── unistd.h
  │   └── util
  │       ├── atomic.h
  │       ├── crc16.h
  │       ├── delay_basic.h
  │       ├── delay.h
  │       ├── eu_dst.h
  │       ├── parity.h
  │       ├── setbaud.h
  │       ├── twi.h
  │       └── usa_dst.h
  └── lib
      ├── avr25
      │   ├── crtat86rf401.o
      │   ├── crtata5272.o
      │   ├── crtata6616c.o
      │   ├── crtattiny4313.o
      │   ├── crtattiny43u.o
      │   ├── crtattiny441.o
      │   ├── crtattiny44a.o
      │   ├── crtattiny44.o
      │   ├── crtattiny45.o
      │   ├── crtattiny461a.o
      │   ├── crtattiny461.o
      │   ├── crtattiny48.o
      │   ├── crtattiny828.o
      │   ├── crtattiny841.o
      │   ├── crtattiny84a.o
      │   ├── crtattiny84.o
      │   ├── crtattiny85.o
      │   ├── crtattiny861a.o
      │   ├── crtattiny861.o
      │   ├── crtattiny87.o
      │   ├── crtattiny88.o
      │   ├── libat86rf401.a
      │   ├── libata5272.a
      │   ├── libata6616c.a
      │   ├── libattiny4313.a
      │   ├── libattiny43u.a
      │   ├── libattiny441.a
      │   ├── libattiny44.a
      │   ├── libattiny44a.a
      │   ├── libattiny45.a
      │   ├── libattiny461.a
      │   ├── libattiny461a.a
      │   ├── libattiny48.a
      │   ├── libattiny828.a
      │   ├── libattiny841.a
      │   ├── libattiny84.a
      │   ├── libattiny84a.a
      │   ├── libattiny85.a
      │   ├── libattiny861.a
      │   ├── libattiny861a.a
      │   ├── libattiny87.a
      │   ├── libattiny88.a
      │   ├── libc.a
      │   ├── libm.a
      │   ├── libprintf_flt.a
      │   ├── libprintf_min.a
      │   ├── libscanf_flt.a
      │   ├── libscanf_min.a
      │   └── tiny-stack
      ├── avr3
      ├── avr ...
      ├── avr
      ├── avr4
      ├── avr5
      ├── crtat90c8534.o
      ├── crtat90s1200.o
      ├── crtat90s4414.o
      ├── crtat90s4434.o
      ├── crtat90s8515.o
      ├── crtat90s8535.o
      ├── crtattiny11.o
      ├── crtattiny12.o
      ├── crtattiny15.o
      ├── crtattiny28.o
      ├── libat90c8534.a
      ├── libat90s1200.a
      ├── libat90s4414.a
      ├── libat90s4434.a
      ├── libat90s8515.a
      ├── libat90s8535.a
      ├── libattiny11.a
      ├── libattiny12.a
      ├── libattiny15.a
      ├── libattiny28.a
      ├── libc.a
      ├── libm.a
      ├── libprintf_flt.a
      ├── libprintf_min.a
      ├── libscanf_flt.a
      ├── libscanf_min.a
      └── tiny-stack
          ├── crtat90s2313.o
          ├── crtat90s2323.o
          ├── crtat90s2333.o
          ├── crtat90s2343.o
          ├── crtat90s4433.o
          ├── crtattiny22.o
          ├── crtattiny26.o
          ├── libat90s2313.a
          ├── libat90s2323.a
          ├── libat90s2333.a
          ├── libat90s2343.a
          ├── libat90s4433.a
          ├── libattiny22.a
          ├── libattiny26.a
          ├── libc.a
          ├── libm.a
          ├── libprintf_flt.a
          ├── libprintf_min.a
          ├── libscanf_flt.a
          └── libscanf_min.a
  
      

Tooling

Toolchain

GCC + Bin Utils + AVR Dudes

  • Command Line Tools voor het compileren en branden van de code
    • avr-gcc: compiler + assembler + linker
    • avr-objcopy: object copy
    • avr-dude: programmer
  • Het is mogelijk om deze zelf aan te roepen
  • Call naar de tools worden gemaakt vanuit de Arduino IDE
    • Zet bij preferences verbose output aan voor compilatie
    • Zie Program Calls door Arduino
  • Debugger laten we buiten beschouwing

Simpel voorbeeld


$ avr-gcc -Wall -g -Os -mmcu=attiny13 -o main.bin main.c
$ avr-objcopy -j .text -j .data -O ihex main.bin main.hex
$ avrdude -p attiny13 -c usbasp -U flash:w:main.hex:i -F -P usb
      

Program Calls door Arduino


/home/luytsm/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/luytsm/.arduino15/packages/arduino/hardware/avr/1.6.23/cores/arduino -I/home/luytsm/.arduino15/packages/arduino/hardware/avr/1.6.23/variants/eightanaloginputs /tmp/arduino_build_552226/sketch/quick.ino.cpp -o /dev/null
Generating function prototypes...
/home/luytsm/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/luytsm/.arduino15/packages/arduino/hardware/avr/1.6.23/cores/arduino -I/home/luytsm/.arduino15/packages/arduino/hardware/avr/1.6.23/variants/eightanaloginputs /tmp/arduino_build_552226/sketch/quick.ino.cpp -o /tmp/arduino_build_552226/preproc/ctags_target_for_gcc_minus_e.cpp
/usr/bin/arduino-ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_552226/preproc/ctags_target_for_gcc_minus_e.cpp
Compiling sketch...
/home/luytsm/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/luytsm/.arduino15/packages/arduino/hardware/avr/1.6.23/cores/arduino -I/home/luytsm/.arduino15/packages/arduino/hardware/avr/1.6.23/variants/eightanaloginputs /tmp/arduino_build_552226/sketch/quick.ino.cpp -o /tmp/arduino_build_552226/sketch/quick.ino.cpp.o
Compiling libraries...     
      

Nu terug naar de bits

Voordat we de juiste eentjes en nulletjes kunnen zetten, moeten we die leren manipuleren vanuit code

Bit Operaties

Manipulatie op bitniveau

  • Microcontroller werkt met 8bit geheugenplaatsen
  • Code schrijven met hoge precisie
  • Efficiëntie

Status van een lamp

  • Status van een lamp: 1 ? 0
  • 1 bit informatie
  • sizeof(int) = 4 bytes
    • Overkill
  • Kleinste datatype =
    • Byte / Char
  • Oplossing
    • Data verzamelen in één element

int pinValues[8] = {0, 1, 0, 1, 0, 1, 0, 1}
      

byte pinValuesBin = 0b01010101; //or
byte pinValuesHex = 0x55; 
      

Bitwise Operators

Symbol Operator
& bitwise AND
| bitwise OR
^ bitwise XOR
<< left shift
>> right shift
~ bitwise NOT (one's complement) (unary)

Bitwise Operators

Bitwise AND (&)

bit a bit b a & b (a AND b)
0 0 0
0 1 0
1 0 0
1 1 1

11001000 & 
10111000 = 
-------- 
10001000
        

Bitwise OR (|)

bit a bit b a | b (a OR b)
0 0 0
0 1 1
1 0 1
1 1 1

11001110 | 
10011000 =
-------- 
11011110
        

Bitwise Operators

Bitwise XOR (^)

 

bit a bit b a ^ b (a XOR b)
0 0 0
0 1 1
1 0 1
1 1 0

11001110 ^
10011000 =
-------- 
01010110
        

Bitwise NOT (~)

AKA Bit Toggle

bit a ~a (complement of a)
0 1
1 0
empty
empty

~ 11001110
---------- 
= 00110001
        

Bitwise Operators

Left Shift


11001110 << 1
-------- 
= 10011100
      

11001110 << 5
-------- 
= 11000000 
      
  • LSB Opvullen met 0
  • Maal 2

Right Shift


11001110 >> 1
-------- 
= 01100111
      

11001110 >> 5
-------- 
= 00000110
      
  • MSB Opvullen met 0
  • Delen door 2

Los Op


11001011 & 
11110000 =  ?
      

1100 1011 & 
1111 0000 =  
11000000
      

byte x = 0xA3;
byte y = 0xF;
byte z = x & y // z = ?
      

0xA3  &  // 1010 0011
0xF   =  // 0000 1111
0x3      // 0000 0011
      

00000000 ^
10101010 = ?
      

0000 0000 ^
1010 1010 =
1010 1010
      

byte x = 0x4C
byte y = 0xB;
byte z = x ^ y // z = ?
      

0x4C ^ // 0100 1100
0xB  = // 0000 1011
0x47   // 0100 0111
      


1 << 4 = ?
      


1 << 4 = 
0x10      //0001 0000
      


byte y = 0x6;
byte z = y << 4 // z = ?
      


0x6 << 4 // 0000 0110 
0x40         // 0110 0000
      

Los Op


11000110 | 
00001111 = ?
      

1100 0110 | 
0000 1111 = 
1100 1111
      

byte x = 0x4B;
byte y = 0xF0;
byte z = x | y // z = ?
      

0x4B |    // 0100 1011
0xF0 =    // 1111 0000
0xFB      // 1111 1011


      


~ 11110000 = ?
      


~ 1111 0000 = 
  0000 1111
      


byte y = 0x3;
byte z = ~y // z = ?
      


~ 0x3 = // 0011
  0xC   // 1100
      


00010110 >> 5 = ?
      


0001 0110 >> 5 =
1100 0000
      


byte y = 0xF0;
byte z = y >> 0x4 // z = ?
      


0xF0 >> 0x4 // 1111 0000
0xF         // 0000 1111
      
Meer oefeningen: klik hier

Bitwise Assigment

Symbol Operator
&= bitwise AND assignment
|= bitwise inclusive OR assignment
^= bitwise exclusive OR assignment
<<= left shift assignment
>>= right shift assignment

Bit mask

Bits Activeren


   10010101   10100101
OR 11110000   11110000
=  11110101   11110101
      

byte x = 0x95A5;
byte y = 0xF0F0
byte z = x | y;
byte z = 0xF5F5;
      

Bits (De)Selecteren


    10010101   10100101
AND 00001111   00001111
=   00000101   00000101
      

byte x = 0x95A5;
byte y = 0x0F0F
byte z = x & y;
byte z = 0x05F5;
      

Bit mask

Bitwaarde togglen


    10011101   10010101
XOR 00001111   11111111
=   10010010   01101010
      

byte x = 0x9D95;
byte y = 0x0FFF
byte z = x ^ y;
byte z = 0x926A;
      

Bitwaarde opvragen


    10011101   10010101
AND 00001000   00001000
=   00001000   00000000
      

byte x = 0x97A5;
byte y = 0x0808;
byte z = x & y;
byte z = 0x0808;
      

Vaak willen we maar een bit manipuleren

Vaak gebruikte bit operaties

  • Set a bit
  •  my_byte |= (1 << n)
  • Clear a bit
  •  my_byte &= ~(1 << n)
  • Toggle a bit
  •  my_byte ^= (1 << n)
  • Test a bit
  •  my_byte & (1 << n)

Bit Order

MSB Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 LSB

Los Op

  • Zet bit 0 tot 3 van een byte
  • my_byte |= 0xF
  • Zet bit 5 en 6 van een byte
  • my_byte |= (0x3 << 5)
  • Clear bit 4 van een byte
  • my_byte &= ~(1 <<  4)
  • Clear bit 4 tot 7 een van byte
  • my_byte &= ~(0xF <<  4)
  • Toggle bit 1 van een byte
  • my_byte ^= (1 <<  0)
  • Toggle bit 3 en 4 van een byte
  • my_byte ^= (0x3 <<  3)
  • Zet de 3 MSB bits van de byte 0x7A met de 3 LSB van de byte 0x2F
    Zet de 3 LSB van 0x12 met de 3 MSB van 0x2F
  • 
    byte mask = 0x2F
    byte x = 0x7A
    byte y = 0x12
    x |= (mask << 5)
    y |= (mask >> 3) 
            

Oefening

  • Schrijf een rotate left (ROL) functie
  • Maak gebruik van unsigned integers
  • Maak de oefening op de Arduino

byte rol(byte b, byte amount)
{
amount = amount % 8;
uint8_t tmp = b;
tmp = (tmp >> (8-amount)) | (tmp << amount);
return tmp;
}
  

Intro bit manipulaties done

Toepassen op delen van de microcontroller

Onderwerp voor de volgende les