lørdag den 11. december 2010

Øvelse 12

UART, RS232 og en rigtig god guide her: http://www.easysw.com/~mike/serial/serial.html

Koden indsættes, kig godt på den, der er nemlig //kommentarer i den :)

read.cpp, koden der læser fra en port, og dermed modtager det:


#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

//opretter POSIX terminal struct, hvor vi kan indsætte muligheder
struct termios options;

void main()
{
//åbner porten, /dev/ttyS0 angiver at der arbejdes med seriel kabler. (J1)
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

/*fcntl () angiver om den skal være blocking*/
fcntl(fd, F_SETFL, 0);

//IOCTL kald der ligger i .
tcgetattr(fd, &options);

//Her opsættes BAUD til 115200
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);

//Aktiver modtageren og fastsætte lokale mode ...
options.c_cflag | = (clocal | CREAD);

//Sæt de nye muligheder for porten ...
tcsetattr(fd, TCSANOW, &options);

//opsætter til ingen paritet 8-bit (8N1):
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;


//laver en modtage buffer
char buf [21];
read(fd,buf, 20);

//udskriver det til skærmen:
printf("Der modtages: %s",buf);
}


For write.cpp, skrives der til porten, dermed betyder det at vi sender:

#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

struct termios options;
void main()
{
int fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &options);

//Sætter Baud til 115200
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);

//Aktiver modtageren og fastsætte lokale mode ...
options.c_cflag |= (CLOCAL | CREAD);

//Sæt de nye muligheder for porten ...
tcsetattr(fd, TCSANOW, &options);

//opsætter til ingen paritet 8-bit (8N1):
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;

//opretter skrive buffer:
char buf [21];

//Udskrver at brugeren gerne må skrive noget:
printf("Indskriv tekst (max 20 char.)\n\r");

//low-tec CIN:
gets(buf);

//skriver til filen, og dermed sender den noget:
write(fd,buf, sizeof(buf));
}

Vi sluttede de to porte sammen, med et null modem, startede to terminaler op, kørte read i den ene, og write i den anden, og minsandten om den ikke sendte:


og modtog:


mandag den 29. november 2010

Øvelse 11
Hvilken type RAM kreds er benyttet og hvad er karakteristisk for denne type?
Der benyttes en SRAM-kreds, som har følgende karakteristika:
  • Har større footprint end det typiske alternetriv DRAM.
  • Ligesom DRAM, kræver konstant spænding.
  • Er dyre end DRAM, på grund af det større footprint.

Hvor mange addresselinier skal vi bruge for at tilgå al memory i den nævnte kreds? -og kan vi det med GPMC interfacet?
Memory-interfacet er 16-bit.
OMAP har dumt nok kun til et 10-bits interface:
så vi kan ikke bruge de sidste 6-bit, og man kan derfor overveje og bruge en billigere kreds, der bliver bedre udnyttet.


Hvor lang tid kan kredsen holde data efter strømafbrydelse, hvis vi benytter et CR2032 knapcelle batteri?
Q=i*t,
mens i = max 2 µA

det giver 112500 timer,
eller 12,83 år.

Hvad er den maksimale databåndbredde for kredsen?
Vi aflæser tiden til 85 ns, og antallet af bit er 16.
det giver 188235294.118 bit/s som giver 180 megabit

LED
Hvilke adresser skal man skrive til for at sætte værdierne af de 5 LED banke?
Man skriver til adresse A10 A9 og A8.
dette kunne være: 0x4000 0 x 0 0
hvor x angiver bit 11:8 i hex, som vi derfra kan vælge.

Beskriv en skrive cyklus for at sætte værdien af lysdioderne på bank 3.
Man skriver til 0x4000 0 3 0 0, hvor med 3 vælger bank 3.
kredsen 74hc138 omsætter adressen 3 til en "chipselect" til bank 3, og data fra bussen routes der hen.

mandag den 22. november 2010

Opgave 10
Vi laver denne magiske kode der belaster CPU vildt..:
denne har denned tid:

vi mindsker antallet af læsninger manuelt, og derved optimere brugen af cache:
Som giver os denne væsentligt forbedre tid (1/5 hurtigere end normalt):


Yderligere optimering kan fås med compiler flag -O0 til -O3, der optimere diverse.
vi så dog ingen væsentligere forbedringer, kun på få ms, så dette er ikke hver at dokumentere....





mandag den 15. november 2010

Opgave 9
Assambly-koden:
#Testing r-format arithmetic operators

#init registers
.register $s0 -10
.register $s1 5
.register $s2 3


main: add $s3, $s1, $s1 #5+5
add $s4, $s1, $s0 #5+-10
sub $s5, $s1, $s2 #5-3
sub $s6, $s2, $s1 #3-5
and $s7, $s2, $s1 #011 AND 101
exit:

Hvad gør den??

Den første instruktion tager register 1 (5) og lægger sammen med register 1 (5), og putter svaret i reg 3.
Den anden instruktion tager register 1 (5) og lægger sammen med register 0 (-10), og putter svaret i reg 4.
Den tredje instruktion tager register 2 (3) og trækker fra register 1 (5), og putter svaret i reg 5.
Den fjerde instruktion tager register 1 (5) og trækker fra register 2 (3), og putter svaret i reg 6.
Den femte instruktion tager register 2 (3) og adder med register 1 (5), og putter svaret i reg 7.

Opgave 1 : Basic arithmetic
• Hvilke enheder benyttes?
Programcounter
Sender med specifikke mellemrum adressen til næste kommando.
Programinkriminator
Inkrimentere programcounterværdien
'Programinstruktionsstørrelseinkriminator
Udsender en hardcoded værdi af kommandolængden.
Instruktionshukommelsen
Udsender instruktionen tilsvarende til det som kommandoen peger på i dens hukommelse.
Splitter
Opdeler instruktionen i de forskellige registre og funktionaliteter.
Registerbank
Indlæser de to inputregistre, samt klargør outputregistret.
Registerbankkontrol
Vælger funktionalitet af registerbanken
Hovedaritmetik
Udregner arimitikopgaven på 2 input.
Hovedaritmetikkontrol
Angiver funktionalitet til hovediarimtikken ud fra instruktion.

• Hvilke afhængigheder eksisterer?
alle enheder afhænger af hinanden

• I hvilken rækkefølge udføres operationerne?
Programcounteren sætter takten for hele svineriet.
rækkefølgen for svineriet er:
der hentes en instruktion, instruktionen opdeles i registrer og funktionalitet, parallelt sendes registrende til registerbanken, samt funktionaliteten sendes til Hovedaritmetikkontrol, registerbanken modtager kontrolfunktionalitet fra registerkontrollen, parallelt klargøres outputregistret mens værdien fra de to inputregistre hentes og outputtes, hovedarimitik modtager funktionalitet fra hovedaritmitkkontrol, hovedaritmitik modtager to inputværdier, behandler aritmetisk og outputter dem, registerbanken modtager resultatet, og putter det ned i det klargjorte register.

• Svarer det overens med det forventede?

mandag den 8. november 2010

Opgave 8
I denne øvelse skal vi lave en tilføjelse til vores GPIO driver. Vha et ioctl kald skal det være muligt at sætte en output pin til at toggle med et fast interval.

Implementer ioctl kald
ved ioctl kladet udskriver vi til kernen:
IOCTL kladet implimenteres ligesom en read eller write funktion i driveren. IOTCL kan tilgås fra userspace ligesom read og write, og bruges ofte til at sætte driveren op til noget speceilt, det kunne f.eks. være baud-rate på en serial-driver.
IOCTL funktionen skal kaldes med et IOCTL-nummer. Da ioctl-numrene er globale skal man først sikre sig at man vælger et nummer der ikke er optaget. Alt under 1000 er med stor sikkerhed optaget allerede (enten af systemet eller andre drivere) så derfor valgte vi to vilkårlige tal over 1000. Valget faldt på 1101 og 1102.

Det første vi gør er at tilføje IOCTL i file_operations, så muligheden for IOCTL er der:
I vores file_operations struct tilføjer vi muligheden for ioctl-kald.

struct file_operations mygpio_Fops =
{
.owner = THIS_MODULE,
.open = mygpio_open,
.release = mygpio_release,
.write = mygpio_write,
.read = mygpio_read,
.ioctl = mygpio_ioctl,
};

Dernæst skal vi angive vores magiske IOCTL numre:
#define JOE1 1101
#define JOE2 1102

Så implimentere vi IOCTL-funktionen:
size_t mygpio_ioctl(struct inode* Inode, struct file* filep, unsigned int cmd, unsigned long arg)
{
int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
switch(cmd)
{
case JOE1:
printk(KERN_ALERT "Det var en etter\n");
break;
case JOE2:
printk(KERN_ALERT "Det var en toer %i\n", arg);
break;
default:
printk(KERN_ALERT "Defualt default!\n");
break;
}
return 0;
}

Læg mærke til case: JOE2, hvor vi samtidig udskriver arg, denne angiver nemlig hvilke argumenter vi sender med.

Vi laver en applikation der kan kontrollere driveren fra userspace:

#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/timer.h>

int main()
{

int fd = open ( "/dev/joenode1", O_RDWR | 0666);

ioctl(fd, 1101); //burde udskrive Det var en etter til kernen
close(filePtr);
int fd = open ( "/dev/joenode1", O_RDWR | 0666);

ioctl(fd, 1102, 7); //sender 7 med som argument
//burde udskrive Det var en toer 7 til kernen
close(filePtr);
return 0;
}

Test:
Først indsætter vi modulet, og opretter noden, og køre dmesg:

kører vores testprogram, og ser hvad der sker:

Implementer toggler
vi valgte kun at implimentere en timer der ikke belastede CPU'en da denne er den mest anvendelige, og vi var lidt bagefter med CPAC opgaverne..


Til timeren brugte vi siden her som inspiration:
og kom frem til følgende kode som fungerede:
size_t mygpio_ioctl(struct inode* Inode, struct file* filep, unsigned int cmd, unsigned long arg)
{
int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
switch(cmd)
{
case INIT_TIMER:
printk("Init timer!\n");
init_timer(&my_timer);
//jiffies og HZ er system vaiabler der angiver tiden
my_timer.expires = jiffies + arg*HZ;
my_timer.function = timer_func;
my_timer.data = arg;
add_timer(&my_timer);
break;
case SET_INTERVAL:
printk("Setting interval %i\n", arg);
my_timer.expires = jiffies + arg*HZ;
break;
case EXIT_TIMER:
printk("Exit timer!\n");
del_timer_sync(&my_timer);
break;
default:
printk("Defualt case entered!\n");
}
return 0;
}

//og her den timer_func der udføres når den udløber
static void timer_func(long int arg)
{
printk("Entering timer_func");
//init_timer(&my_timer);
add_timer(&my_timer);
my_timer.expires = jiffies + arg*HZ;
my_timer.function = timer_func;
my_timer.data = arg;
if(val == 1)
{
printk("Setting val %i\n", val);
gpio_set_value(139, 1);
val = 0;
}
else
{
printk("Setting val %i\n", val);
gpio_set_value(139, 0);
val = 1;
}
}

VI fik LED'erne til at blinke med et interval vi sendte fra userspace med et kald til IOCTL, med numret for den anden IOCTL kommando, hvor vi kunne sætte intervallet for blinket, og den gjorde og alt var godt : ) : ) : ) : )

mandag den 11. oktober 2010

Opgave 7
- Find ud af hvordan DAC7612 er forbundet til OMAP’en
Forbundet Bus 1, chipsselect 3

- Find ud af DAC7612’s SPI karakteristika.
CPOL = 1;
CPHA = 1;

- Indsæt værdier i board struct’en, ret number of bit_per_word i spi_probe
i ads7870-core.c ændres structen således:
.bus_num = 1,
.chip_select = 3,
i ads7870-core.c ændres metoden __devinit ads7870_spi_probe
så bit_pr_word = 14;

- Indsæt nogle debug printk’er

Implementer write
Da vi skal implimentere write før vi kan sætte en default værdi, gør vi dette først. Efter vi har sat defaultværdien implementerer i wiritefunktionen (ads7870_cdrv_write i filen dac7612.c)

ssize_t ads7870_cdrv_write(struct file *filep, const char __user *ubuf,
size_t count, loff_t *f_pos)
{
int minor, len, value;
char kbuf[MAXLEN];

minor = MINOR(filep->f_dentry->d_inode->i_rdev);

len = count < (MAXLEN - 1) ? count : MAXLEN;

copy_from_user(kbuf, ubuf, len);

sscanf(kbuf, "%i", &value);

dac7612_write(minor, value);
return count;
}


Hvorefter vi kan måle på Devkittet at udgangen ændrede spænding når vi skrev til devicet.
echo 1000 >/dev/dac0
giver en spænding på 1000mV
.

mandag den 4. oktober 2010

Øvelse 6 - Interrputs

Implementer Interrupt request/free
Requester interrupt i interrupt.c (modificeret øvelse 5)
indsættes i init lige før return:

unsigned int IRQ = gpio_to_irq(130);


request_irq(IRQ, myISR, IRQF_TRIGGER_RISING, "Joe", NULL);
printk("IRQ-line: %d", IRQ);
//der ses med dmesg hvilket IRQ-linie vi får tildelt.

implimenter pseudo myISR, som kører printk(KERN_ALERT "IRQ event!!!\n");.

Implementer ISR
Der er et eksempel på wait() på side 160 i LDD3.
Tilføj følgende kode i toppen af filen, som global variabel.

static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag = 0;

I mygpio_read( ) på linie 278 og 279 tilføjes følgende kode.
flag = 0;
wait_event_interruptible(wq, flag!=0);

I mypgio_isr( ) implimenteres således:

vi forbinder interruptbenet til GROUND
indsætter modul:
insmod interrupts.ko

VI skifter benet over til VCC, og bagefter til GND igen.

vi kigger i dmesg, og ser at der sket nogle interrupts.