giovedì 22 maggio 2008

NO al nucleare

Vaffanculo.
Anche io mi incazzo qualche volta. Prima guardatevi questo video.

Poi ricordate..."I popoli non dovrebbero aver paura dei propri governi, sono i governi che dovrebbero aver paura dei propri popoli." Thomas Jefferson
NO al nucleare. Iniziate a tremare maledetti.

P.S. La luna segna il sentiero. Ripeto: La luna segna il sentiero.

mercoledì 21 maggio 2008

PCI Express 1x

E' un progetto ambizioso. Prendere una scheda PCI express (R) 1x e collegarci dei segnali direttamente sul pettine, per utilizzare la scheda senza inserirla nella mother board di un PC. L'idea è venuta ad un collega programmatore, privo di nozioni inerenti l'hardware. Per iniziare, ho bisogno di un socket PCIe 1x da dissaldare da una mother board defunta ma di recente costruzione. Non ne ho a magazzino. L'hardware che recupero è troppo obsoleto e quel tipo di socket si trova nelle mother board che vengono mandate in riparazione in garanzia. Mi sa che dovrò fare un giretto fra i rivenditori di zona e frugare nella "spazzatura" tecnologica che si accumula nel corso dei loro interventi di "riparazione". sperando in un colpo di fortuna. Il pinout di un socket PCI Express comprende l'alimentazione a 3.3 e 12 volts (oltre alla massa), un canale Jtag (interessante per l'accesso diretto al processore), un bus SMB (I2C 1 wire) anche questo interessantissimo per sviluppare una cascata di sensori collegabili direttamente alla mother board ed altri segnali che per ora non mi interessano.
PCI-E è un bus seriale che usa due coppie di segnali differenziali a basso voltaggio (Low-voltage Differential Signal LVDS) con transfer rate da 2.5Gb/s in ciascuna direzione [una coppia in trasmissione ed una coppia in ricezione].
Ho già in mente alcune soluzioni per espandere le possibilità di utilizzo di un paio di PC che giacciono in attesa di modifiche. Stay tuned.

P.S. Ultrasuoni e calore nel camino. Ripeto: Ultrasuoni e calore nel camino.

domenica 18 maggio 2008

Modulo driver per kernel 2.6.x

Dopo un pò di googling in rete, ho trovato alcuni esempi di come programmare i moduli per il kernel 2.4.x
Il nuovo kernel 2.6.x attualmente in distribuzione presenta alcune differenze che hanno reso inutili gli esempi pubblicati sino ad oggi. Vediamo quindi qui alcune considerazioni utili a realizzare un modulo per la porta parallela, che mi servirà a pilotare il motore stepper unipolare già postato in precedenza e che è in fase di sviluppo. Premetto che maggiori info si possono trovare nei repository ufficiali della distribuzione che si utilizza (inutile mettere qui i link che ce ne sono a iosa)
Il kernel di linux fa un largo uso di driver caricabili dinamicamente quando serve, il che ci dà la possibilità di evitare la ricompilazione dello stesso in caso fosse necessario utilizzare delle periferiche nuove. Un altra comodità di linux è che "tutto è un file", ovvero i dispositivi possono essere utilizzati come se fossero dei files. Ci posso scrivere e ci posso leggere. Ciò ci permette di avere accesso ad aree di memoria protette o accedere a basso livello alle periferiche che normalmente equipaggiano i PC. Per fare ciò è necessario "vedere" il dispositivo nella gerarchia /dev. Negli esempi di codice che seguono, si utilizza il linguaggio C. Il codice è preso da vari esempi, cercando di tradurre alcune istruzioni scritte in klingon che si trovano "spezzettate" in vari post di altri programmatori.

Apertura del driver
static int miaporta_open(struct inode *inode, struct file *filep)
{
//ci limitiamo a scrivere un messaggio
printk("Dispositivo aperto\n");
return 0;
}

Chiusura del driver
static int miaporta_release(struct inode *inode, struct file *filep)
{
//anche qui scriviamo solamente un messaggio
printk("Dispositivo chiuso\n");
return 0;
}

La scrittura sul driver
static ssize_t miaporta_write(struct file *filep, const char *buf, size_t count, loff_t *f_pos)
{
outb(0x00,0x37A); // porta parallela 1 in uscita
outb(buf[0],0x37B); // Scrittura sul registro ADDRESS
return 0;
}

La lettura dal driver
static ssize_t miaporta_read(struct file *filep, char *buf, size_t count, loff_t *f_pos)
{
outb(0x20,0x37A); // Porta parallela1 in Input
buf[0]=inb(0x37B); // lettura dal registro ADDRESS
return 0;
}

Occorre ora associare le procedure alle funzioni dei files. Per farlo, quest’ultime devono essere esportate al sistema. Questo lavoro viene svolto riempendo una struttura particolare di tipo ”file operations”, definita nell’header file ”linux/fs.h”.

struct file_operations epp_fops =
{
owner: THIS_MODULE,
open: miaporta_open,
release: miaporta_release,
read: miaporta_read,
write: miaporta_write,
};

Per l'inizializzazione del modulo occorre anche associare, con la funzione "register chardev", un ben definito device al nostro driver. Basta passare come parametri, nell’ordine, il major-char-number (20), una stringa con il nome del driver e la struttura con registrate le funzioni specifiche di accesso.

static int __init init_mod(void)
{
int result;
if ((result = register_chrdev(20, "miaporta", &epp_fops)) < style="color: rgb(51, 204, 0);">Chiusura del driver (deregistrazione9

static void __exit end_mod(void)
{
unregister_chrdev(20, "miaporta");
printk("Driver MIAPORTA unloaded.\n");
}

Per ultimo occorre aggiungere la linea in testa MODULE_LICENSE("GPL"); (o altre opzioni disponibili in base al tipo di licenza prescelto) e in fondo

module_init(init_mod);
module_exit(end_mod);

Per compilare, occorre creare un Makefile come segue:

obj-m:= miaporta_drv.o
KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.mod.* *.o *.ko

Una volta compilato occorre caricare il modulo con insmod ./miaporta_drv.ko e per poterlo utilizzare basta dare il comando mknod -m 0666 /dev/miaporta c 20 0
Funziona?. non lo so, devo ancora provare.

In attesa che sviluppi il codice e inizi a testarlo vediamo come si prevede di utilizzarlo all'interno del programma che lo utilizza...

#include "fcntl.h"
#include "stdio.h"
int main()
{
char buffer[1];
int fd;
fd=open("/dev/miaporta",O_RDWR);
buffer[0]=0x00;
write(fd,buffer,1,NULL); //scrivo il byte
read(fd,buffer,1,NULL); //leggo i byte
printf("Valore : 0x%02x\n",buffer[0]);
close(fd);
}

Dovrebbe funzionare. Se nei prossimi giorni trovo il tempo di svilupparlo e mi accorgo che qualcosa non va, provvederò alle modifiche. Per ora STOP. Una domenica passata al PC approfittando del maltempo mi pare sufficiente. Ora un pò di relax. un abbraccio

P.S. Mille bit fanno un megabit. Ripeto: Mille bit fanno un megabit.