AT32UC3C - Einstieg in die Programmierung

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

Motivation

Ich beschäftige mich nunmehr seit einem Jahr im Rahmen eines Praktikums bei der Bosch Engineering GmbH mit dem AT32UC3C0512C. Ich habe in dieser Zeit einige Erkenntnisse gewonnen, die ich Euch hier gerne zur Verfügung stellen möchte. Während meiner Recherche habe ich die Erfahrung gemacht, dass man einige Quellen zur A- und B-Serie des AT32UC3 findet, jedoch wenig zur C-Serie. Das Atmel Software Framework war für mich in den meisten Fällen ebenfalls nicht brauchbar, da es viel zu komplex aufgebaut ist. Daher hoffe ich, dass ich mit diesem Beitrag einigen von Euch den Einstieg in die Programmierung mit dem AT32UC3C erleichtern kann. Viel Erfolg!

Architektur

Architektur AT32UC3C.png

Der AT32UC3C0512C besitzt einen 32-bit-RISC-Prozessorkern mit 512KB Flash und 64KB SRAM. Der Prozessor kann mit einer Taktfrequenz von bis zu 66MHz betrieben werden. Der Prozessorkern ist umgeben von Peripheriemodulen, die für die verschiedenen Funktionen des Controllers zuständig sind. Die einzelnen Module erhalten ihren Arbeitstakt über die drei Peripheriebusse PBA, PBB und PBC (graue Pfeile im Bild), deren Takte jeweils einzeln konfiguriert werden können. Diese Peripheriebusse sind neben der HighSpeedBusMatrix (HSB, orangener Kasten im Bild) für den Informationsaustausch zwischen den verschiedenen Modulen zuständig. Die lila dargestellten Module sind für interne Funktionen wie Taktfrequenzen, Speicherorganisation, Interruptfreigaben usw. zuständig. Die grün dargestellten Module sind dagegen für die Kommunikation mit dem Controllerumfeld verantwortlich. In meinen weiteren Beiträgen werde ich vor allem auf die Konfiguration der wichtigen internen Funktionen eingehen, die notwendig sind, um den Mikrocontroller zu betreiben.

Headerfiles

Folgende Headerfiles müssen in einem Programm für den AT32UC3 eingebunden sein:

- intypes.h

- avr32/io.h

Der avr32/io-Header fragt ab, welcher Mikrocontroller als Device ausgewählt wurde und bindet einen dazu passenden Header ein. Dieser wiederum bindet eine große Anzahl von Header-Files ein, die Defines für die einzelnen Funktionsmodule des Controllers enthalten. In den Headerfiles sind sowohl den Registern, als auch den im Datenblatt erwähnten wichtigen Bits und Werten jeweils Namen zugewiesen, um den Programmcode lesbarer zu gestalten. Diese Namen sind nach einer Systematik benannt, die hier im nächsten Beitrag „Beschreiben von Registern“ erläutert wird.

Systematische Bezeichnung von Registern, Bitfeldern, Masken

Hier soll die Systematik der Namen erklärt werden, die für die Bezeichnung von Registern, Bitfeldern und Masken in den Systemheader-Files hinterlegt sind:

Register

AVR32_< MODUL-NAME >.< REGISTER-NAME >

Beispiel: AVR32_USART0.cr

Mit dieser Bezeichnung wird die absolute Adresse eines Registers angegeben. Im Beispiel handelt es sich um das USART-Control Register, das die absolute Adresse 0xFFFF2800 hat. AVR32_USART0.cr heißt also dasselbe wie 0xFFFF2800.

Wenn es mehrere Register gibt, die gleich heißen und zur Identifizierung mit einer laufenden Nummer versehen sind, sieht die Bezeichnung so aus:

AVR32_< MODUL-NAME >.< REGISTER-NAME >[n]

Beispiel: AVR32_SCIF.oscctrl[0]

Register-Offset

AVR32_< MODUL-NAME >_< REGISTER-NAME >

Beispiel: AVR32_USART_CR

Diese Bezeichnung gibt den Registeroffset, also die Speicherposition im jeweiligen Modulspeicher, an. Im Beispiel ist das CR (Control Register) das erste Register im Modul USART und hat damit den Offset 0x0000. Es gibt fünf USART-Module (USART0-USART4), wobei alle Module gleich aufgebaut sind. Damit ist der Registeroffset überall gleich.

Bit-Felder

AVR32_< MODUL-NAME >_< REGISTER-NAME >_< BITFELD-NAME >

Beispiel: AVR32_USART_CR_TXEN

Bitfelder sind ein- oder mehrere Bit große Registerbereiche, die auf eine bestimmte Weise beschrieben werden müssen, damit ein entsprechende Funktion ausgeführt wird. Jedes Bitfeld, dem eine Funktion zugewiesen ist, hat einen zur Funktion passenden Namen, der im Datenblatt in der Registerübersicht zusammen mit der zugehörigen Funktion vermerkt ist. Die Bitfeldzeichnung gibt die Position im Register an.

Im Beispiel heißt das Bitfeld TXEN (Transmitter Enable). Da es sich beim TXEN um das Bit 6 im CR-Register handelt, ist die Bezeichnung AVR32_USART_CR_TXEN gleichbedeutend mit der Zahl 6.

Absolute Adressierung von Bitfeldern

AVR32_<MODUL-NAME>.< REGISTER-NAME >.< BITFELD-NAME >

Beispiel: AVR32_USART.CR.txen

Wenn man ein Bitfeld in einem Register direkt beschreiben will, kann man die absolute Adresse des Registerbereichs auf diese Weise angeben.

Offset

AVR32_< MODUL-NAME >_< REGISTER-NAME >_< BITFELD-NAME >_OFFSET

Beispiel: AVR32_USART_CR_TXEN_OFFSET

Diese Bezeichnung ist gleichbedeutend mit der Bezeichnung des Bitfeldes selbst. Sie enthält lediglich das Zusatzwort _OFFSET, um besser zu verdeutlichen, dass es sich um die entsprechende Dezimalzahl für das Bit im Register handelt.

Masken

AVR32_< MODUL-NAME >_< REGISTER-NAME >_< BITFELD-NAME >_MASK

Beispiel: AVR32_USART_CR_TXEN_MASK

Die Bitfeldbezeichnung mit dem Zusatz _MASK steht für eine Hexadezimalzahl, die als Binärzahl umgerechnet an der Stelle des bezeichneten Bits eine 1 enthält. Setzt man sie mit dem Register gleich, setzt man an der entsprechenden Stelle das Bit. Im Beispiel ist AVR32_USART_CR_TXEN_MASK gleichbedeutend mit 0x00000040.

Beschreiben von Registern mit LOCK-Funktion

Die Systemregister des AT32UC3C, die für die grundlegenden Initialisierungsschritte zuständig sind (z.B. im SCIF-Register und im PM-Register), sind oft mit einer Lock-Funktion verstehen. Das bedeutet, sie sind nicht ohne weiteres zum Beschreiben freigegeben. Um die Register trotzdem beschreiben zu können, müssen sie zunächst durch Beschreiben eines UNLOCK-Registers entsperrt werden.

Anlegen von Macros zum Entsperren von LOCK-Registern:

  1. define SCIF_UNLOCK(reg) (AVR32_SCIF.unlock = (unsigned long)(AVR32_SCIF_UNLOCK_KEY_VALUE<<AVR32_SCIF_UNLOCK_KEY_OFFSET)|(reg))
  1. define PM_UNLOCK(reg) (AVR32_PM.unlock = (unsigned long)(AVR32_PM_UNLOCK_KEY_VALUE<<AVR32_PM_UNLOCK_KEY_OFFSET)|(reg))

Das Makro zum Entsperren der SCIF-Register heißt hier SCIF_UNLOCK. In das AVR32_SCIF.unlock-Register wird zunächst im entsprechenden Bitfeld ein Unlock-Key (0xAA) eingegeben. Gleichzeitig wird im Adressteil des Unlock-Registers die Adresse des zu entsperrenden Registers eingetragen. Da jedes gesperrte Modul-Register ein eigenes Unlock-Register besitzt, muss als Adresse nur der Registeroffset einzutragen werden.

Der Entsperrbefehl muss unmittelbar vor dem Beschreiben des Registers vom Prozessor bearbeitet werden, da das Register nur für den nächsten Taktzyklus freigegeben ist.

Verwendung der Makros:

Möchte man das „Oscillator0 control register“ (OSCCTRL0, Registeroffset 0x0024 im SCIF) beschreiben, so geht man wie folgt vor. In diesem Fall wird der Oscillator 0 aktiviert.


//Registerbereich OSCCTRL0 wird entsperrt, Konstante AVR32_SCIF_OSCCTRL entspricht 0x0024 SCIF_UNLOCK(AVR32_SCIF_OSCCTRL);

//OSC Enable Bit auf 1 setzen AVR32_SCIF.oscctrl[0] = (1<<AVR32_SCIF_OSCEN_OFFSET);

System Control Interface (SCIF) und Power Manager (PM)

Das System Control Interface ist für folgende Funktionen zuständig:

  • Konfiguration der internen Oszillatoren (OSCCTRL0, OSCCTRL1, OSCCTRL32)
  • Konfiguration der beiden Phasenregelschleifen (PLL0 und PLL1), die zur Modufikation und Vervielfachung (bis maximal 66MHz) der Oszillatortakte verwendet werden können.
  • Konfiguration und Aktivierung von Generic Clocks. Es gibt einige Module (z.B. USB, CAN …), die spezifische Taktfrequenzen benötigen. Diese werden als Generic Clock bereitgestellt und müssen vor der Nutzung aktiviert und durch Setzen von Teilern oder Faktoren eingestellt werden.

Der Power Manager ist für folgende Funktionen zuständig:

  • Festlegung der Taktquelle für die Systemtakte. Hier wird festgelegt, mit welchem Oszillator (intern oder extern) oder PLL der Arbeitstakt für die CPU, sowie die drei Peripheriebusse (PBA, PBB, PBC) und die High-Speed-Bus-Matrix (HSB) erzeugt werden soll. Außerdem können Teiler und Faktoren zur Anpassung des CPU-/PBx-Takte gesetzt werden. Der HSB-Takt muss immer gleich dem CPU-Takt sein.
  • Taktmaskierung: In den ClockMASK-Registern können Modultakte durch löschen des zum Modul gehörenden Bits angeschaltet werden, um Energie zu sparen. Im Default-Zustand sind alle Modultakte aktiviert.
  • Verwaltung der Energiesparfunktionen (Sleepmodes) und Hard-/Softwareresets