Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/imre-kerr/tdt4258
Browse files Browse the repository at this point in the history
  • Loading branch information
imre-kerr committed Feb 17, 2014
2 parents 2afa76a + 411c71d commit c8c61a3
Show file tree
Hide file tree
Showing 14 changed files with 607 additions and 28 deletions.
1 change: 0 additions & 1 deletion ov1_report/Abstract forslak K.txt

This file was deleted.

14 changes: 0 additions & 14 deletions ov1_report/EoA

This file was deleted.

5 changes: 0 additions & 5 deletions ov1_report/Introduction.txt

This file was deleted.

31 changes: 23 additions & 8 deletions ov1_report/report.tex
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@

\documentclass[a4paper, 12pt]{article}
\usepackage{graphicx}
\title{Exercise 1, Group 2 \\ TDT4258 \\ Energy Efficient Computer Systems}
\author{Per Bachmann \and Imre Kerr \and Kristian Volden}
\begin{document}
\maketitle
\begin{abstract}
In this report, we describe and discuss the first exercise in the Energy efficient computer systems course. In this excercise we developed a simple program for an EFM32 Giant Gecko microcontroller. The program lets the user manipulate a row of LEDs (light emitting diodes) using buttons on a game pad. Low energy modes and interrupts are used to reduce power consumption.
In this report, we describe and discuss the first exercise in the Energy efficient computer systems course. In this excercise we developed a simple program for an EFM32 Giant Gecko microcontroller. The program lets the user manipulate a row of LEDs (light emitting diodes) using buttons on a game pad. Low energy modes and interrupts are used to reduce power consumption.
\end{abstract}
\pagebreak
\section{Introduction} % (fold)
\label{sec:introduction}
A microcontroller is a CPU with the most necessary components included on the same silicon dye, i.e. the flexible GPIO I/O controller. The purpose of this integration is to allow for more minimal and energy efficient designs. The GPIO controller is included in the EFM32GG microcontroller and is essential for this exercise.
An import aspect of this exercise is to use interrupts for controlling the buttons on the game pad. An interrupt, in contrast to continuously polling the I/O, allows the CPU to enter a low power state if there is no work to be done. The interrupt will then awake the CPU and start the necessary interrupt handler routine.
A microcontroller is a CPU with the most necessary components included on the same silicon die, i.e. the flexible GPIO I/O controller. The purpose of this integration is to allow for more minimal and energy efficient designs. The GPIO controller is included in the EFM32GG microcontroller and is essential for this exercise.

An important aspect of this exercise is to use interrupts for controlling the buttons on the game pad. An interrupt, in contrast to continuously polling the I/O, allows the CPU to enter a low power state if there is no work to be done. The interrupt will then awake the CPU and start the necessary interrupt handler routine.

For the exercise we were given access to an EFM32GG-DK3750 development board with an ARM Cortex M3 based EFM32GG microcontroller. We were also given access to a custom peripheral game pad, with buttons and LEDs, for the development board. For this microcontroller, we were expected to write a small program in the assembly programming language. The program should allow a user to use the buttons on the game pad to control the LEDs. The program should do this while using as little energy as possible.
% section introduction (end)

\section{Description and Methodology} % (fold)
\label{sec:description_and_methodology}
\subsection{Description of Program} % (fold)
\subsection{Description of the Program} % (fold)
\label{sub:description_of_program}
The functionality of the program is very simple. A single LED will be lit on the gamepad, and the user can press button 1 and 3 (``left'' and ``right'') to move the light left or right.

Expand Down Expand Up @@ -54,13 +58,19 @@ \section{Results and Tests} % (fold)
\label{sec:results_and_tests}
\subsection{Functional Tests} % (fold)
\label{sub:functional_tests}
\begin{figure}[!ht]
\centerline{\includegraphics[width=0.7\textwidth]{IMG064}}
\centerline{\includegraphics[width=0.7\textwidth]{IMG065}}
\caption{Pressing the buttons makes the light move.}
\label{fig:buttons}
\end{figure}
\begin{enumerate}
\item Pressing the left (button 1) or right (button 3) buttons should make the light move left or right, respectively. \\
Result: It does.
\item The buttons should not glitch, i.e. a press should not be registered twice.\\
Result: This did happen occasionally.
\end{enumerate}
For the last one, our theory is that the built-in glitch filter in the EFM32GG has a period that is too short (typically 10-50ns according to the data sheet). Since it is implemented in hardware, this period isn't user configurable.
For the last one, our theory is that the built-in glitch filter in the EFM32GG has a period that is too short (10-50ns according to the data sheet). Since it is implemented in hardware, this period isn't user configurable.
% subsection functional_tests (end)

\subsection{Power Consumption} % (fold)
Expand All @@ -70,15 +80,15 @@ \section{Results and Tests} % (fold)
\caption{eaProfiler graph showing power consumption}
\label{fig:profiler}
\end{figure}
The graph in Figure \ref{fig:profiler} shows the difference in power consumption for one button pressed and no buttons pressed. When no buttons are pressed, the power consumption is very low, only 5.54 $\mu$ W. When a button is pressed, the power consumption increases considerably. Note that this is due to current flowing through the switch to ground, not because the MCU is running all the time.
The graph in Figure \ref{fig:profiler} shows the difference in power consumption for one button pressed and no buttons pressed. When no buttons are pressed, the power consumption is very low, only 5.54 $\mu$W. When a button is pressed, the power consumption increases considerably. Note that this is due to current flowing through the switch to ground, not because the MCU is running all the time.

Also note that the LED is not included in the calculation, because it would dwarf everything else.
% subsection power_consumption (end)
% section results_and_tests (end)

\section{Evaluation of Assignment} % (fold)
\label{sec:evaluation_of_assignment}
The assignment was a good introduction to using the EFM32GG microcontroller. The compendium was easy to follow and made the task manageable. However the use of the reference manual was tedious, as it was not always easy to look up the information you actually needed. As an example we tried to find out how to return from the interrupt handler; looking at the quick reference and tried to find the instruction there, but were unable to do so. You may be able to find it in the 900 page reference manual, but trying to search through the manual for a task like this should not be necessary. Even though you want us to look at the reference manual, it should be for those things that we could realistically be expected to find there. Other than this, the exercise served as a good introduction to the course.
The assignment was a good introduction to using the EFM32GG microcontroller. The compendium was easy to follow and made the task manageable. However the use of the reference manual was tedious, as it was not always easy to look up the information you actually needed. As an example we tried to find out how to return from the interrupt handler; looking at the quick reference and tried to find the instruction there, but were unable to do so. You may be able to find it in the 900 page reference manual, but trying to search through the manual for a task like this should not be necessary. Even though you want us to look at the reference manual, it should be for those things that we could realistically be expected to find there. Other than this, the exercise served as a good introduction to the course.
% section evaluation_of_assignment (end)

\section{Conclusion} % (fold)
Expand All @@ -88,6 +98,11 @@ \section{Conclusion} % (fold)

\section{References} % (fold)
\label{sec:references}

\begin{itemize}
\item TDT4258 Exercise Compendium, from the course pages on It's Learning.
\item ARM Thumb-2 Quick Reference, from the course pages on It's Learning.
\item EFM32GG990 Datasheet, \\
\textit{http://cdn.energymicro.com/dl/devices/pdf/d0046\_efm32gg990\_datasheet.pdf}
\end{itemize}
% section references (end)
\end{document}
29 changes: 29 additions & 0 deletions ov2_code/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Example Makefile
#
# Exercise 2, TDT4258

CC=arm-none-eabi-gcc
LD=arm-none-eabi-gcc
OBJCOPY=arm-none-eabi-objcopy

CFLAGS=-mcpu=cortex-m3 -mthumb -g -std=c99 -Wall
LDFLAGS=-mcpu=cortex-m3 -mthumb -g -lgcc -lc -lcs3 -lcs3unhosted -lefm32gg -Llib
ASFLAGS=-mcpu=cortex-m3 -mthumb -g
LINKERSCRIPT=lib/efm32gg.ld

ex2.bin : ex2.elf
${OBJCOPY} -O binary $< $@

ex2.elf : ex2.o timer.o dac.o gpio.o interrupt_handlers.o
${LD} -T ${LINKERSCRIPT} $^ -o $@ ${LDFLAGS}

%.o : %.c
${CC} ${CFLAGS} -c $< -o $@

.PHONY : upload
upload :
-eACommander.sh -r --address 0x00000000 -f "ex2.bin" -r

.PHONY : clean
clean :
-rm -rf *.o *.elf *.bin *.hex
22 changes: 22 additions & 0 deletions ov2_code/dac.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <stdint.h>
#include <stdbool.h>

#include "efm32gg.h"
#include "ex2.h"

void setupDAC()
{
/*
TODO enable and set up the Digital-Analog Converter
1. Enable the DAC clock by setting bit 17 in CMU_HFPERCLKEN0
2. Prescale DAC clock by writing 0x50010 to DAC0_CTRL
3. Enable left and right audio channels by writing 1 to DAC0_CH0CTRL and DAC0_CH1CTRL
4. Write a continuous stream of samples to the DAC data registers, DAC0_CH0DATA and DAC0_CH1DATA, for example from a timer interrupt
*/

*CMU_HFPERCLKEN0 |= CMU2_HFPERCLKEN0_DAC0;
*DAC0_CTRL = 0x50010;
*DAC0_CH0CTRL = 1;
*DAC0_CH1CTRL = 1;
}
143 changes: 143 additions & 0 deletions ov2_code/efm32gg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include <stdint.h>

// GPIO

#define GPIO_PA_BASE 0x40006000
#define GPIO_PB_BASE 0x40006024
#define GPIO_PC_BASE 0x40006048

#define GPIO_PA_CTRL ((volatile uint32_t*)(GPIO_PA_BASE + 0x00))
#define GPIO_PA_MODEL ((volatile uint32_t*)(GPIO_PA_BASE + 0x04))
#define GPIO_PA_MODEH ((volatile uint32_t*)(GPIO_PA_BASE + 0x08))
#define GPIO_PA_DOUT ((volatile uint32_t*)(GPIO_PA_BASE + 0x0c))
#define GPIO_PA_DOUTSET ((volatile uint32_t*)(GPIO_PA_BASE + 0x10))
#define GPIO_PA_DOUTCLR ((volatile uint32_t*)(GPIO_PA_BASE + 0x14))
#define GPIO_PA_DOUTTGL ((volatile uint32_t*)(GPIO_PA_BASE + 0x18))
#define GPIO_PA_DIN ((volatile uint32_t*)(GPIO_PA_BASE + 0x1c))
#define GPIO_PA_PINLOCKN ((volatile uint32_t*)(GPIO_PA_BASE + 0x20))

#define GPIO_PB_CTRL ((volatile uint32_t*)(GPIO_PB_BASE + 0x00))
#define GPIO_PB_MODEL ((volatile uint32_t*)(GPIO_PB_BASE + 0x04))
#define GPIO_PB_MODEH ((volatile uint32_t*)(GPIO_PB_BASE + 0x08))
#define GPIO_PB_DOUT ((volatile uint32_t*)(GPIO_PB_BASE + 0x0c))
#define GPIO_PB_DOUTSET ((volatile uint32_t*)(GPIO_PB_BASE + 0x10))
#define GPIO_PB_DOUTCLR ((volatile uint32_t*)(GPIO_PB_BASE + 0x14))
#define GPIO_PB_DOUTTGL ((volatile uint32_t*)(GPIO_PB_BASE + 0x18))
#define GPIO_PB_DIN ((volatile uint32_t*)(GPIO_PB_BASE + 0x1c))
#define GPIO_PB_PINLOCKN ((volatile uint32_t*)(GPIO_PB_BASE + 0x20))

#define GPIO_PC_CTRL ((volatile uint32_t*)(GPIO_PC_BASE + 0x00))
#define GPIO_PC_MODEL ((volatile uint32_t*)(GPIO_PC_BASE + 0x04))
#define GPIO_PC_MODEH ((volatile uint32_t*)(GPIO_PC_BASE + 0x08))
#define GPIO_PC_DOUT ((volatile uint32_t*)(GPIO_PC_BASE + 0x0c))
#define GPIO_PC_DOUTSET ((volatile uint32_t*)(GPIO_PC_BASE + 0x10))
#define GPIO_PC_DOUTCLR ((volatile uint32_t*)(GPIO_PC_BASE + 0x14))
#define GPIO_PC_DOUTTGL ((volatile uint32_t*)(GPIO_PC_BASE + 0x18))
#define GPIO_PC_DIN ((volatile uint32_t*)(GPIO_PC_BASE + 0x1c))
#define GPIO_PC_PINLOCKN ((volatile uint32_t*)(GPIO_PC_BASE + 0x20))

#define GPIO_EXTIPSELL ((volatile uint32_t*)(GPIO_PA_BASE + 0x100))
#define GPIO_EXTIPSELH ((volatile uint32_t*)(GPIO_PA_BASE + 0x104))
#define GPIO_EXTIRISE ((volatile uint32_t*)(GPIO_PA_BASE + 0x108))
#define GPIO_EXTIFALL ((volatile uint32_t*)(GPIO_PA_BASE + 0x10c))
#define GPIO_IEN ((volatile uint32_t*)(GPIO_PA_BASE + 0x110))
#define GPIO_IFC ((volatile uint32_t*)(GPIO_PA_BASE + 0x11c))

// CMU

#define CMU_BASE2 0x400c8000

#define CMU_HFPERCLKDIV ((volatile uint32_t*)(CMU_BASE2 + 0x008))
#define CMU_HFCORECLKEN0 ((volatile uint32_t*)(CMU_BASE2 + 0x040))
#define CMU_HFPERCLKEN0 ((volatile uint32_t*)(CMU_BASE2 + 0x044))
#define CMU_CMD ((volatile uint32_t*)(CMU_BASE2 + 0x024))

#define CMU2_HFPERCLKEN0_DAC0 (1 << 17)
#define CMU2_HFPERCLKEN0_PRS (1 << 15)
#define CMU2_HFPERCLKEN0_GPIO (1 << 13)
#define CMU2_HFPERCLKEN0_TIMER1 (1 << 6)

#define CMU_HFCORECLKEN0_DMA (1 << 0)

// TIMER1

#define TIMER1_BASE 0x40010400

#define TIMER1_CMD ((volatile uint32_t*)(TIMER1_BASE + 0x04))
#define TIMER1_IEN ((volatile uint32_t*)(TIMER1_BASE + 0x0c))
#define TIMER1_IFC ((volatile uint32_t*)(TIMER1_BASE + 0x18))
#define TIMER1_TOP ((volatile uint32_t*)(TIMER1_BASE + 0x1c))
#define TIMER1_CNT ((volatile uint32_t*)(TIMER1_BASE + 0x24))

// NVIC

#define ISER0 ((volatile uint32_t*)0xe000e100)
#define ISER1 ((volatile uint32_t*)0xe000e104)
#define ICER0 ((volatile uint32_t*)0xe000e180)
#define ICER1 ((volatile uint32_t*)0xe000e184)
#define ISPR0 ((volatile uint32_t*)0xe000e200)
#define ISPR1 ((volatile uint32_t*)0xe000e204)
#define ICPR0 ((volatile uint32_t*)0xe000e280)
#define ICPR1 ((volatile uint32_t*)0xe000e284)
#define IABR0 ((volatile uint32_t*)0xe000e300)
#define IABR1 ((volatile uint32_t*)0xe000e304)

// IPR

#define IPR_BASE 0xe000e400

#define IPR0 ((volatile uint32_t*)(IPR_BASE + 0x00))
#define IPR1 ((volatile uint32_t*)(IPR_BASE + 0x04))
#define IPR2 ((volatile uint32_t*)(IPR_BASE + 0x08))
#define IPR3 ((volatile uint32_t*)(IPR_BASE + 0x0c))

// EMU

#define EMU_BASE2 0x400c6000

#define EMU_CTRL ((volatile uint32_t*)(EMU_BASE2 + 0x000))

// DAC0

#define DAC0_BASE2 0x40004000

#define DAC0_CTRL ((volatile uint32_t*)(DAC0_BASE2 + 0x000))
#define DAC0_CH0CTRL ((volatile uint32_t*)(DAC0_BASE2 + 0x008))
#define DAC0_CH1CTRL ((volatile uint32_t*)(DAC0_BASE2 + 0x00c))
#define DAC0_IEN ((volatile uint32_t*)(DAC0_BASE2 + 0x010))
#define DAC0_IF ((volatile uint32_t*)(DAC0_BASE2 + 0x014))
#define DAC0_IFS ((volatile uint32_t*)(DAC0_BASE2 + 0x018))
#define DAC0_IFC ((volatile uint32_t*)(DAC0_BASE2 + 0x01c))
#define DAC0_CH0DATA ((volatile uint32_t*)(DAC0_BASE2 + 0x020))
#define DAC0_CH1DATA ((volatile uint32_t*)(DAC0_BASE2 + 0x024))
#define DAC0_COMBDATA ((volatile uint32_t*)(DAC0_BASE2 + 0x028))

// DMA

#define DMA_BASE 0x400c2000

#define DMA_STATUS ((volatile uint32_t*)(DMA_BASE + 0x0000))
#define DMA_CONFIG ((volatile uint32_t*)(DMA_BASE + 0x0004))
#define DMA_CTRLBASE ((volatile uint32_t*)(DMA_BASE + 0x0008))
#define DMA_ALTCTRLBASE ((volatile uint32_t*)(DMA_BASE + 0x000c))
#define DMA_CHUSEBURSTS ((volatile uint32_t*)(DMA_BASE + 0x0018))
#define DMA_CHUSEBURSTC ((volatile uint32_t*)(DMA_BASE + 0x001c))
#define DMA_REQMASKC ((volatile uint32_t*)(DMA_BASE + 0x0024))
#define DMA_CHENS ((volatile uint32_t*)(DMA_BASE + 0x0028))
#define DMA_CHALTC ((volatile uint32_t*)(DMA_BASE + 0x0034))
#define DMA_IFC ((volatile uint32_t*)(DMA_BASE + 0x1008))
#define DMA_IEN ((volatile uint32_t*)(DMA_BASE + 0x100c))
#define DMA_CH0_CTRL ((volatile uint32_t*)(DMA_BASE + 0x1100))

// PRS

#define PRS_BASE 0x400cc000

#define PRS_CH0_CTRL ((volatile uint32_t*)(PRS_BASE + 0x010))

// System Control Block

#define SCR ((volatile uint32_t*)0xe000ed10)
#define SYSTICK_CTRL ((volatile uint32_t*)0xe000e010)
#define SYSTICK_LOAD ((volatile uint32_t*)0xe000e014)

Loading

0 comments on commit c8c61a3

Please sign in to comment.