AVR Weblog

Winfried Mueller, www.reintechnisch.de

20.03.2008 :: Lockbits sicher?

Ist der Programmcode in einem gelockter AVR-Prozessor wirklich sicher? Wenn man auf der Flylogic Homepage so ins Lesen kommt, schwindet einem langsam das Vertrauen, dass man dieser Möglichkeit sehr viel Vertrauen schenken kann. Da gibt es z.B. Prozessoren, die man aufätzen kann, um dann die Lockbits mit UV-Licht zu bestrahlen, um sie zu kippen. Und dann kann man den Code auslesen. Es gibt also Möglichkeiten, wenn auch noch nicht bei jedem Prozessor praktisch nachgewiesen. Manche werden leichter zu knacken sein, andere schwerer.

Das Problem ist: Wenn einmal bekannt ist, wie es geht und man diesen Prozess halbwegs im Griff hat, dann können Firmen in China das als Dienstleistung anbieten. Man schickt sein Chip dort hin und bekommt ein paar Tage später per E-Mail das Hex-File zugeschickt. Natürlich, nachdem man einen entsprechenden Betrag per Kreditkarte bezahlt hat. Und weil Personal in China sehr billig ist, sind es lediglich die einmaligen Investitionen für teure Gerätschaften, die die Kosten verursachen. Angeblich soll es schon Unternehmen geben, die solche Dienstleistungen anbieten.

In einer Zeit der Globalisierung und des Internet fallen viele Barrieren. Man braucht nicht mehr selber teure Gerätschaften, sondern kauft sich Dienstleistungen irgendwo weltweit ein. Weltwissen vernetzt sich, nicht jeder muss selber nachdenken und Zeit investieren. Auch die Argumentation zieht nicht mehr, dass man ja erstmal sehr viel investieren muss, um einen Chip überhaupt zu knacken. Wenn einmal ein Kunde da ist, der viel Geld dafür bezahlt, ist es irgendwann mal geknackt. Und dann ist jeder verdiente zusätzliche Euro durch weitere Kunden gutes Geld. Und wenn es nur 1000 Euro sind.

Eine Geschäftsidee, die nur überlebt, wenn der Code geschützt bleibt, ist nicht ohne. Man kann sich nicht auf die Lockbits von Prozessoren verlassen. Vieles ist nur eine Frage der Zeit.

Weblinks:

12.10.2007 :: AES Verschlüsselung auf AVR

08.02.2006 :: Power-Down Stromaufnahme

Wenn man batteriebetriebene Geräte mit niedrigem Stromverbrauch und langer Standbyzeit aufbauen möchte, braucht man vor allem sehr geringe Standby-Ströme. Ich denke da an Geräte wie Fernbedienungen, Langzeitmessgeräte, Uhren.

Interessant dabei ist auch, wie hoch die Stromaufnahme des internen Watchdog ist. Dieser kann den Prozessor ja in regelmäßigen Abständen aus dem Power-Down Modus aufwecken. Das ist wichtig, wenn man regelmäßig etwas pollen muss.

Die AVR-Prozessoren unterscheiden sich dabei in den Stromaufnahmen. Hier mal ein kleiner Überblick. Angegeben sind die Maximalwerte bei 3V, die typischen Werte liegen deutlich darunter (ohne Watchtdog bis Faktor 10).

TypPower-Down mit Watchdog / uAPower-Down ohne Watchdog / uA
Tiny12152
Tiny13161
Tiny15152
Tiny231362
Tiny26153
Tiny44168
Tiny45152
Mega8L283
Mega16154

08.01.2006 :: ATtiny 45 - Probleme bei dynamischer Taktumschaltung

Der ATtiny 45 hat ein sehr interessantes Feature: Die Taktfrequenzumschaltung im laufenden Betrieb. So kann man aus Stromspargründen, ähnlich wie bei einem Centrino -Prozessor, den Systemtakt runterfahren. Hierfür sorgt ein Prescaler, der den Takt bis zum Faktor 256 teilen kann.

Beim Brennen des Chips lässt sich bereits festlegen, was dieser Prescaler für einen Defaultwert annehmen soll: 0 oder 8. Dies geschieht über die CKDIV8 Fuse. Es handelt sich dabei jedoch nur um einen Defaultwert, der ins CLKPR Register geladen wird. Dieses Register kann man nun per Programm mit Teilerfaktoren von 1..256 belegen. Allerdings muss man eine festgelegte Programmierabfolge beachten, was wohl zum Schutz vor falscher Umprogrammierung gedacht ist - falls ein Programm mal verrückt spielt.

In einem ersten Befehl muss 0b10000000 in das CLKPR geschrieben werden. Eine 1 auf Bit 7 (CLKPCE) enabled die Veränderung des Prescalers für genau 4 Taktzyklen. Innerhalb dieser muss man nun den neuen Wert hineinschreiben (Bit0..3), wobei dabei dann CLKPCE mit 0 beschrieben werden muss. Damit wir das Timing einhalten können, muss während dieser Zeit jeder Interrupt gesperrt sein.

Eine typische Herangehensweise wäre nun diese:

 
.def a           = r16


              ;Speed Divider Set
              cli
              ldi a, 0b10000000
              out CLKPR, a
              ldi a, 0b00000000
              out CLKPR, a
              sei

Darauf reagierte mein Chip jedoch nicht und mir bleibt dabei unverständlich, warum. Aus der Not heraus kam dann folgende Idee: Den IO-Bereich kann man genauso über Ram-Adressierung erreichen, wenn man 0x20 hinzuaddiert. Also versuchte ich, CLKPR über direkte RAM-Addressierung zu beschreiben:

 
.def a           = r16


              ;Speed Divider Set
              cli
              ldi a, 0b10000000
              sts CLKPR+0x20, a
              ldi a, 0b00000000
              sts CLKPR+0x20, a
              sei

Eigentlich ist das ja identisch mit vorherigem Programm. Und trotzdem: Hiermit funktionierte die Taktveränderung (jedoch nicht beim 6.4MHz Takt, hierzu hatte ich aber schon was zuvor geschrieben).

Würde mich interessieren, was andere hier für Erfahrungen machen. Vielleicht liegt es auch an den noch recht frühen Chips, die aus der 32KW 2005 stammen.

08.01.2006 :: ATtiny 45 - 6.4MHz interner Takt mysteriös

Der ATtiny lässt sich ja intern auf 8 MHz oder 6.4 MHz setzen. Der 6.4 MHz Takt wurde nur aus Kompatiblitätsgründen zum ATtiny 15 eingeführt. Und genau dieser Takt verhält sich bei meinen Tests sehr merkwürdig. Zum einen ist der Strombedarf wesentlich höher, als bei der Nutzung des 8 MHz Taktes. Zum anderen funktioniert z.B. die CKDIV8 Fuse nicht - egal wie ich sie einstelle, der Takt bleibt identisch. Evtl. liegt der Wurm aber auch im AVR-Studio im Zusammenspiel mit dem AVRISP Programmer.

07.01.2006 :: Simple Test

Kleine, simple Testprogramme sind genau das Richtige, wenn man erstmal grundsätzlich überprüfen will, ob ein Chip funktioniert oder die Programmierumgebung korrekt arbeitet. Es ist sozusagen ein "Hello World", wie man es aus Hochsprachen kennt.

Hier ein getestetes Programm für den ATtiny 45, welches nur eine Leuchtdiode an PB3 permanent toggelt. Frequenz sollte auf 8MHz eingestellt sein, CKDIV8 Fuse ist gesetzt.

 
; test1.asm - Simple Test: Blink PB3
; Interner RC-Oszi, 1MHz, Tiny 45
; Beginn: 07.01.2006, Stand: 08.01.2006
; Author: Winfried Mueller, www.reintechnisch.de  
;
; Fuses:
;   Clock: 8MHz
;   Clock Divide/8: enabled
;
; PORTB
; PB0: IN    P   NC
; PB1: IN    P   NC
; PB2: IN    P   NC
; PB3: OUT   -   LED (Low aktiv)
; PB4: IN    P   NC
; PB5: IN    P   Reset

.include "tn45def.inc"

; Register Definition

;   General Purpose
.def a           = r16
.def b           = r17
.def c           = r18

;   Interrupt
.def i_a         = r19
.def sSREG       = r1


;--------------------------------------
; Interruptvektoren
;--------------------------------------

              rjmp RESET
              reti           ;INT0
              reti           ;PCINT0
              reti           ;TIM1_COMPA
              reti           ;TIM1_OVF
              reti           ;TIM0_OVF
              reti           ;EE_RDY
              reti           ;ANA_COMP
              reti           ;ADC
              reti           ;TIM1_COMPB
              reti           ;TIM0_COMPA
              reti           ;TIM0_COMPB
              reti           ;WDT
              reti           ;USI_START
              reti           ;USI_OVF


RESET:
MAIN:         ;Stackpointer Init
              ldi a, low(RAMEND)
              out SPL, a
              ldi a, high(RAMEND)
              out SPH, a


              ;IO-Init
              ldi a, 0b11111111
              out PORTB, a
              ldi a, 0b00001000
              out DDRB, a

loop:         cbi PORTB, 3
              ldi a, 50
              rcall WAIT_M
              sbi PORTB, 3
              ldi a, 50
              rcall WAIT_M
              rjmp loop

;Zeitschleife
;Übergabe: a - Länge= 10ms * a (a:1..255)
WAIT_M:
WM_0:         ldi b, 0xFF
WM_1:         lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              lpm
              wdr
              wdr
              dec b
              brne WM_1
              dec a
              brne WM_0
              ret


Anmerkungen:

  • Der Stackpointer sollte nach dem Reset lt. Datenblatt auf RAMEND zeigen, weshalb wir ihn nicht explizit initialisieren müssen. Man sollte sich jedoch generell angewöhnen, den Stack immer erst zu initialisieren, weil andere Chips aus der AVR-Reihe diesen nicht automatisch richtig setzen.
  • Die Zeitschleife ist für 1.2MHz berechnet, stimmt hier also nicht genau.

06.01.2006 :: Stromaufnahme ATtiny45

gemessen, @20 Grad, Brownout, Watchdog und Pheripherie disabled, interne Taktquellen

ModeUB/VFrequenz/MHzI/mA
Idle3.08.01.42
Idle4.08.02.04
Idle5.08.02.72
----   
Idle3.08/80.33
Idle4.08/80.44
Idle5.08/80.56
----3.0  
Idle3.00.1280.07
Idle4.00.1280.08
Idle5.00.1280.09
----   
Active3.08.02.86
Active4.08.03.90
Active5.08.05.24
----   
Active3.08/80.59
Active4.08/80.82
Active5.08/81.09
----   
Active3.00.1280.11
Active4.00.1280.14
Active5.00.1280.17
----   
Power Down3.0--0.1uA
Power Down4.0--0.3uA
Power Down5.0--0.5uA

(8/8 bedeutet 8 MHz interner RC Oszillator und Prescaler 8 = 1MHz)

30.12.2005 :: Ausgangsstrom unterschiedlich je nach Modell

Der ATTiny 12/15 kann gerade H-Seitig wenig treiben. Mehr als 5mA sind kaum sinnvoll, weil die Spannung zu stark einbricht. L-seitig dagegen schafft er 20mA bei 0.5 V Spannung. Der ATTiny 12/15 nimmt da eine Sonderstellung ein, viele andere Chips können durchaus 20 mA auch H-Seitig treiben, bei 5 V sind es unter 1V Abfall. Bei 2.7 Volt sind immerhin noch 10 mA bei unter 1V Abfall möglich. Wahrscheinlich haben die Mosfet Treiber bei niedrigeren Spannungen einen höheren RDSon.

Interessant auch, dass der Tiny 12 oder 15 gegen L recht viel treiben können. Da nimmt der Tiny 13 mit seinen nur 10 mA eine Sonderstellung ein.

Tiny 2313, Tiny 26, Mega 16 verhalten sich ähnlich, können also recht viel H-seitig wie L-seitig treiben.

Typ@5V@4V H mA@5V@0.5V L mA@2.7V@2V H mA@2.7V@0.5VL mA
Tiny 126,022,02,512,0
Tiny 1328,010,011,06,0
Tiny 156,022,02,512,0
Tiny 231335,020,015,012,0
Tiny 2633,020,014,011,0
Mega 1635,018,013,011,0

(Tiny45 keine Daten vorhanden.)

28.12.2005 :: Schaltzeitpunkte CBI/SBI Portbefehle

SBI setzt den Port nach dem ersten Takt auf High. CBI setzt den Port nach dem letzten Takt (=zweiten) auf Low. Getestet beim ATTiny 12, andere Prozessoren könnten sich da anders verhalten.

05.12.2005 :: Strombedarf Prozessoren bei 32KHz Uhrenquarz

@: 25 Grad, ohne Watchdog, Brownout, AD

ProzessorModeFrequenzSpannungStrom/uA
ATTiny12Active32K3.055.0
ATTiny12Active32K4.585.0
ATTiny12Idle32K3.07.0
ATTiny12Idle32K4.515.0
----    
ATTiny26Active32K3.032.0
ATTiny26Active32K4.545.0
ATTiny26Idle32K3.014.0
ATTiny26Idle32K4.522.0
----    
ATMega8Active32K3.065.0
ATMega8Active32K4.575.0
ATMega8Idle32K3.015.0
ATMega8Idle32K4.525.0

05.12.2005 :: Brownout-Stromaufnahme

Leider braucht der Brownout verhältnismäßig viel Strom. Dies ist besonders bei batteriebetriebenen Geräten ungünstig, besonders wenn der Prozessor permanent an der Batterie klemmt. Faustformel: 50uA Strom permanent sind ungefähr 500mAh Energieverbrauch pro Jahr.

ProzessorSpannungStrom/uA
ATTiny123.045.0
ATTiny124.585.0
----  
ATTiny263.019.0
ATTiny264.523.0
----  
ATTiny23133.017.0
ATTiny23134.522.0
----  
ATMega83.014.0
ATMega84.517.0
----  
ATtiny453.019.0
ATtiny454.021.0
ATtiny455.022.0

(Anmerkung: ATTiny 12 und ATtiny 45 selbst gemessen, weil keine Angabe im Datenblatt)

25.10.2005 :: Erstaunlich hoher I/O-Pin Eingangsstrom

Beim Tiny 12 ist der Input-Leckstrom der I/O-Pins mit 8uA angegeben. Das ist sehr viel. Wahrscheinlich ist gemeint, dass dieser Strom im IC gegen Plus fließt (IC ist Quelle). Das würde bedeuten, dass bei einem Pull-Down Widerstand von 100KOhm ganze 0.8 Volt daran abfallen. Größere Pull-Downs wären gar nicht realisierbar. Umgedreht heißt es, dass ein Strom von 8uA pro Eingangspin fließen können, was den Ruhestromverbrauch enorm anheben kann, insofern dieser Inputpin irgendwie verschaltet ist, z.B. auf Low gehalten wird.

Leider ist kein typischer Wert angegeben. Ich vermute, dass der wesentlich geringer ist.

Beim Tiny 26 sind es nur 1 uA. Ebenso beim Tiny 13.

Andererseits ist der Analoge Eingangswiderstand mit 100MOhm angegeben. Gilt das, wenn ein IO-Pin als ADC-Pin programmiert ist? Werden dann also die störenden 1uA abgeschaltet? Gleiches gilt für den Analog Comparator, der nur mit +-50nA Eingangsstrom angegeben ist.

Nachtrag: Tests haben gezeigt, dass Eingangsströme bei 20 Grad im nA Bereich liegen. Unter welchen Bedingungen so hohe Eingangströme von 8uA auftreten, bleibt unklar.

13.10.2005 :: 32KHz Quarz hat lange Anlaufzeit

Ein 32 KHz Quarz braucht an einem ATtiny 12 mitunter 1-3 Sekunden, bis er wirklich anläuft. Es scheint generell so zu sein, dass diese Quarze lange Zeit brauchen, um anzulaufen. Problematisch ist das, wenn man einen Prozessor in den Power-Down schickt. Dann kann man ihn nicht schnell aufwecken, er braucht einige Sekunden.

Weil jedoch der Tiny12 nur wenige uA im Idle-Modus braucht, ist es hier besser, ihn gar nicht erst in den Power-Down zu schicken.

09.10.2005 :: Reset-Pin Besonderheit

Der Resetpin hat als einziger IO-Pin keine interne Clamping-Diode nach VCC. Dies deshalb, weil beim High-Voltage Programming dieser auf ca. 12 V gelegt werden muss, also weit über VCC.

Beachten sollte man dies, wenn man diesen Pin als Eingang nutzt. Ebenso, wenn man eine externe Resetbeschaltung mit Kondensator macht. Dann sollte eine externe Clampingdiode eingebaut werden.

09.10.2005 :: Prozessortypen und Takt

BezeichnungExt. ClockExt. Quarz32KHz Quarz32KHz internal Cap
ATTiny 12jajajanein
ATTiny 13janeinneinnein
ATTiny 15neinneinneinnein
ATTiny 26jajajaja
ATTiny 2313jajaneinnein
ATMega 8jajajaja

Nachtrag: Die neuen ATtiny 45 und ATtiny 24 sind sehr flexibel, was Takteinstellung angeht. Man kann sogar während des Betriebes den Takt über das Prescaler Register PLKCR in weiten Bereichen verändern.

09.10.2005 :: Wie groß Kondensatoren bei externem Quarz

  • hängt vom Quarz ab
  • 12-56 pf sind typisch, im Zweifelsfall erstmal 22/27 pf ausprobieren
  • bei 32KHz Quarzen kann man auch die internen 36pf Kondensatoren einschalten, gibt es aber nicht bei allen Chips. ATTiny 26 hat es z.B.
  • 32KHz Quarz von Reichelt hat eine Belastungskapazität von 10pF, folglich wären 22 pF geeignet
  • Auch die zusätzliche Kapazität der Portpins und des Platinen-Layouts beachten.

Weblink:

12.09.2005 :: Wie genau interner Clock?

Der interne RC-Oszillator ist natürlich nicht super genau. Er ist abhängig von der Betriebsspannung und der Temperatur.

Betreibt man einen ATtiny 12 mit 3-4.5 Volt, schwankt die Frequenz etwa um 3-4%. In Sachen Temperatur kann man etwa 1% bei 25 Grad Temperaturänderung ansetzen.

Hinzu kommt natürlich noch, dass jeder ATtiny absolut noch eine etwas andere Geschwindigkeit aufweist und kalibriert werden muss.

Wer es genauer braucht, stabilisiert die Versorgungsspannung, sorgt für gleichmäßige Temperatur oder setzt einen externen Quarz ein.

Nachtrag 17.10.2009: Beim Tiny 45 schwankt der interne 128KHz Takt zwischen 3-4.5V um ungefähr 1%. Die Frequenz nimmt mit abnehmender Spannung zu (umgekehrt proportional).

10.09.2005 :: Stacktiefe beachten (ATtiny 12)

Die Stacktiefe ist beim ATtiny 12 sehr begrenzt, gerade mal 3 Ebenen tief. Das muss reichen für Interrupt und Unterroutinen. Insofern sollte man in Interrupt-Routinen keine Unterprogrammaufrufe haben. Im Hauptprogramm darf dann maximal aus einem Unterprogramm ein weiteres Unterprogramm aufgerufen werden. Sonst läuft der Stack über. Stack-Überläufe sind hässliche Fehler, die man nur schwer auffinden kann. Insofern sollte man sich davor in acht nehmen.

10.09.2005 :: Brown-Out Detection braucht Strom

Gerade Batteriebetriebene Geräte sollten auch immer ein aktiviertes Brown-Out Detection haben, damit sich der Prozessor sauber zurücksetzt, wenn die Betriebsspannung mal unterschritten wird.

Leider verbraucht die Brown-Out Detection einiges an Strom, was gerade im Power-Down Modus sehr unangenehm ist.

An einem ATtiny 12 gemessen ergab sich eine Stromaufnahme:

  • @3V mit Brownout: 33uA-48uA, ohne: < 1uA
  • @5V mit Brownout: 82uA-90uA, ohne: < 6uA

Das ist schon empfindlich viel, bedeuten doch 33 uA etwa 30mAh pro Jahr.

Im Datenblatt des ATtiny 12 steht dazu nichts. Jedoch steht beim ATmega 8 etwas dazu: Dort verbraucht der Brownout-Schutz etwa 15-20uA, immer noch einiges, aber deutlich weniger, als beim ATtiny 12.

Abhilfe verschaffen könnte wohl nur ein externer Reset-Baustein oder eine diskrete Brown-Out Detection.

10.09.2005 :: sbi und cbi nur für Register bis 0x1F

Leider kann man die IO-Bitset Befehle sbi und cbi nur für die unteren 32 Register benutzen. Viele Konfigurations-Register liegen jedoch oberhalb von 0x1F, diese können nur mit dem IO Befehl OUT gesetzt werden. Ein Bitweises setzen ist nicht möglich.

 
       sbi GIMSK, PCIE      ; Ups, geht nicht

       ldi r16, 0b01000000
       out GIMSK, a         ; OK

Was jedoch geht: Mit ori und andi arbeiten, um entsprechende Bits mit einer Maske zu setzen oder rückzusetzen.

10.09.2005 :: Sleep Modes (ATtiny12)

Damit die Sleep Modes aktiviert sind, muss im MCU Control Register (MCUCR) Bit 5 gesetzt werden (Sleep Enable). Der Sleep Mode wird über Bit 4 festgelegt. Bei 0 ist der Idle Mode aktiviert, bei 1 ist der Power-Down Mode aktiv.

Wenn diese Einstellungen gemacht sind, kann mit dem Befehl sleep in den Sleep-Zustand geschaltet werden.

Idle Mode: Stoppt die CPU, Timer/Counters, Watchdog und Interrupt sind jedoch aktiv. Achtung: Der Analog-Comparator zieht zusätzlich Strom und muss separat über das ACSR Register abgeschaltet werden.

Power-Down Mode: Stoppt den Oszillator und damit die CPU, Timer/Counter. Der Watchdog und die externen Interrupts jedoch funktionieren weiterhin. Damit ist klar, wie man den Chip wieder zum Leben erweckt: Reset, Watchdog, external Interrupt (level oder pin change).

External Interrupts werden nur erkannt, wenn der Signalwechsel lang genug ist. Dieses Verhalten sorgt dafür, dass Spikes ihn nicht auslösen. Diese Wake-Up Periode ist identisch mit dem clock-counting Part der Reset Periode. Bei RC-Oszillator sind das 6 Clockzyklen, also 6us bei 1MHz.

Stromaufnahme

BedingungStrom in uA
Active @3V, 1MHz800
Idle @3V, 1MHz200
Idle @2V, 1MHz80
Idle @4V, 1MHz400
Idle @5V, 1MHz800
Active @3V, 32KHz55
Active @4.5V, 32KHz85
Idle @3V, 32KHz8
Idle @4.5V, 32KHz15
P-Down @5V<2
P-Down @5V, Watchdog enabled40
P-Down @3V, Watchdog enabled6
P-Down @3V, Analog Comp. Enabled100
P-Down @5V, Analog Comp. Enabled550

Faustformel 10uA Dauerstrom sind 100mAh Verbrauch im Jahr.

Codebeispiel:

 
;Initialisierung
        ldi a, 0b00110000 ;Sleep Enable, Power-Down
        out MCUCR, a    

;Sleep aktivieren
;  Interrupts erstmal sperren
        cli

;  Ports so setzen, dass kein unnötiger Strom fließt
        sbi PORTB, P_LED

;  Interrupts evtl. einschalten für Aufwecken
;  andere Interrupts evtl. ausschalten
        ldi r16, 0b00100000  ;Enable PinChange Int
        out GIMSK, r16        
        ldi r16, 0b00000000  ; Disable Timer Int0
        out TIMSK, r16

;  Abschalten Analog Comparator
        sbi ACSR, ACD
        cbi ACSR, AINBG       ;URef off

;  Interrupts wieder aktivieren
        sei

;  Sleep aktivieren
        sleep

;  Aktion nach Aufwachen
        rjmp START