Trail Sheevaplug OpenBSD
From Tmplab
Contents |
Objectif
- Faire démarrer un kernel ramdisk OpenBSD sur un Sheevaplug, et afficher le dmesg sur le port série.
- Se familiariser avec
- l'architecture physique des ordinateurs
- l'architecture propriétaire ARM
- le debugging JTAG
- la chaine de compilation et le systeme OpenBSD
Modus operandi
Le Code Trail proprement dit commencera le vendredi 1 oct. au soir et se terminera le dimanche 3 oct dans l'apres-midi. Chaque personne qui a des tutos et des docs intéressantes est fortement invitée à les publier ou les référencer sur cette page.
Participants
- dermiste
- James
- phantez
- nizox
Docs
Cross-compilation sur OpenBSD
Il faut d'abord récupérer l'arborescence des sources tel qu'indiqué dans la FAQ 5.3.3, et upgrader le système au snapshot le plus récent (FAQ 5.1 et FAQ 5.3.2).
Il faut ensuite construire la chaine de compilation. Il existe pour cela une infrastructure complète, bien que non documentée. Voici par exemple la procedure a suivre pour une chaine ciblant les machines mvme88k :
# cd /usr/src # TARGET=mvme88k make -f Makefile.cross cross-tools
Vous pouvez aller vous prendre un ou plusieurs café en attendant la fin de la compilation. Votre chaine se retrouvera dans /usr/cross/$TARGET.
Cross-compiler un noyau se fait alors de la meme maniere qu'une compilation standard, à une différence près : il faut rajouter /usr/cross/${TARGET}/usr/${TARGET_ARCH}-unknown-openbsd/bin en tête du PATH. Ce répertoire contient les liens symboliques vers les versions cross- des outils de compilation classiques.
Stub de cross-compilation pour sheevaplug
OpenBSD dispose deja de ports sur ARM. Les headers du port gumstix semblent convenir pour générer des executables pour le sheevaplug.
# cp -R /usr/src/sys/arch/gumstix /usr/src/sys/arch/sheeva
Il faut ensuite éditer le fichier /usr/src/Makefile.cross et rajouter ${TARGET} == "sheeva" dans le test qui énumère les différentes cibles basées sur ARM.
patches pour omconsole
omconsole est un petit utilitaire écrit par matthieu@ qui permet d'accéder au port série du neo freerunner via la libftdi. Le sheevaplug a le meme circuit que le neo freerunner, il suffit donc de rajouter les options kivonbien (c).
--- omconsole.c.orig Tue Apr 6 23:41:29 2010
+++ omconsole.c Fri Jun 11 11:46:33 2010
@@ -66,18 +66,49 @@ interrupt(int sig)
done = 1;
}
+void
+usage()
+{
+ extern char * __progname;
+
+ fprintf(stderr, "usage: %s [-v vid] [-p pid] [-s speed]\n", __progname);
+ exit(1);
+}
+
int main(int argc, char **argv)
{
struct termios tio, saved_tio;
int ret;
+ int ch;
+ int vid = 0x1457;
+ int pid = 0x5118;
+ int speed = 115200;
+ while ((ch = getopt(argc, argv, "v:p:s:")) != -1) {
+ switch (ch) {
+ case 'v':
+ vid = (int)strtol(optarg, NULL, 0);
+ break;
+ case 'p':
+ pid = (int)strtol(optarg, NULL, 0);
+ break;
+ case 's':
+ speed = (int)strtol(optarg, NULL, 0);
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
ftdi_init(&ftdic);
- if((ret = ftdi_usb_open(&ftdic, 0x1457, 0x5118)) < 0)
+ fprintf(stderr, "opening %d:%d\n", vid, pid);
+ if((ret = ftdi_usb_open(&ftdic, vid, pid)) < 0)
errx(2, "unable to open ftdi device: %d (%s)\n",
ret, ftdi_get_error_string(&ftdic));
ftdi_set_interface(&ftdic, INTERFACE_B);
- ftdi_set_baudrate(&ftdic, 115200);
+ ftdi_set_baudrate(&ftdic, speed);
tcgetattr(fileno(stdin), &tio);
memcpy(&saved_tio, &tio, sizeof(struct termios));
configuration d'OpenOCD
source [find board/sheevaplug.cfg] gdb_port 4453 tcl_port 4456 telnet_port 4454 arm7_9 fast_memory_access enable
patches pour libusb
L'acces au port serie et au port JTAG du sheevaplug se fait via la libftdi, qui utilise la libusb. Pour utiliser simultanément ces deux ports, il faut d'abord récupérer l'arborescence des ports tel qu'indiqué dans la FAQ, puis contruire la libusb de la facon suivante :
cd /usr/ports/devel/libusb make patch cd `make show=WRKSRC` patch -Np1 -i ~/libusb-ft2232.diff cd - make install
voici le patch pour la libusb :
diff -Naur a/bsd.c b/bsd.c
--- a/bsd.c Sun Aug 8 22:54:10 2010
+++ b/bsd.c Sun Aug 8 22:57:16 2010
@@ -139,7 +139,6 @@
{
int i;
struct bsd_usb_dev_handle_info *info;
- char ctlpath[PATH_MAX + 1];
info = malloc(sizeof(struct bsd_usb_dev_handle_info));
if (!info)
@@ -147,20 +146,23 @@
dev->impl_info = info;
#ifdef __FreeBSD_kernel__
- snprintf(ctlpath, PATH_MAX, "%s", dev->device->filename);
+ snprintf(dev->ctlpath, PATH_MAX, "%s", dev->device->filename);
#else
- snprintf(ctlpath, PATH_MAX, "%s.00", dev->device->filename);
+ snprintf(dev->ctlpath, PATH_MAX, "%s.00", dev->device->filename);
#endif
- dev->fd = open(ctlpath, O_RDWR);
+ dev->fd = open(dev->ctlpath, O_RDWR);
if (dev->fd < 0) {
- dev->fd = open(ctlpath, O_RDONLY);
+ dev->fd = open(dev->ctlpath, O_RDONLY);
if (dev->fd < 0) {
free(info);
USB_ERROR_STR(-errno, "failed to open %s: %s",
- ctlpath, strerror(errno));
+ dev->ctlpath, strerror(errno));
}
}
+ close(dev->fd);
+ dev->fd = -1;
+
/* Mark the endpoints as not yet open */
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
info->ep_fd[i] = -1;
@@ -199,6 +201,17 @@
{
int ret;
+ if (dev->fd <= 0) {
+ dev->fd = open(dev->ctlpath, O_RDWR);
+ if (dev->fd < 0) {
+ dev->fd = open(dev->ctlpath, O_RDONLY);
+ if (dev->fd < 0) {
+ USB_ERROR_STR(-errno, "failed to open %s: %s",
+ dev->ctlpath, strerror(errno));
+ }
+ }
+ }
+
ret = ioctl(dev->fd, USB_SET_CONFIG, &configuration);
if (ret < 0)
USB_ERROR_STR(-errno, "could not set config %d: %s", configuration,
@@ -206,6 +219,9 @@
dev->config = configuration;
+ close(dev->fd);
+ dev->fd = -1;
+
return 0;
}
@@ -230,6 +246,17 @@
int ret;
struct usb_alt_interface intf;
+ if (dev->fd <= 0) {
+ dev->fd = open(dev->ctlpath, O_RDWR);
+ if (dev->fd < 0) {
+ dev->fd = open(dev->ctlpath, O_RDONLY);
+ if (dev->fd < 0) {
+ USB_ERROR_STR(-errno, "failed to open %s: %s",
+ dev->ctlpath, strerror(errno));
+ }
+ }
+ }
+
if (dev->interface < 0)
USB_ERROR(-EINVAL);
@@ -243,6 +270,9 @@
dev->altsetting = alternate;
+ close(dev->fd);
+ dev->fd = -1;
+
return 0;
}
@@ -442,6 +472,17 @@
struct usb_ctl_request req;
int ret;
+ if (dev->fd <= 0) {
+ dev->fd = open(dev->ctlpath, O_RDWR);
+ if (dev->fd < 0) {
+ dev->fd = open(dev->ctlpath, O_RDONLY);
+ if (dev->fd < 0) {
+ USB_ERROR_STR(-errno, "failed to open %s: %s",
+ dev->ctlpath, strerror(errno));
+ }
+ }
+ }
+
if (usb_debug >= 3)
fprintf(stderr, "usb_control_msg: %d %d %d %d %p %d %d\n",
requesttype, request, value, index, bytes, size, timeout);
@@ -468,6 +509,9 @@
if (ret < 0)
USB_ERROR_STR(-errno, "error sending control message: %s",
strerror(errno));
+
+ close(dev->fd);
+ dev->fd = -1;
return UGETW(req.ucr_request.wLength);
}
test de la chaine
Installez, à l'aide des documents ci dessus, la chaine de cross-compilation pour sheevaplug, la libusb patchée, omconsole patché, et openocd. Dans un répertoire, créez les fichiers suivants :
- init.S
.text
.globl _start
_start:
mov sp, #0x10000000
add sp, sp, #0xa00000
b cstart
- main.c
#define MPPCTL6 *((volatile unsigned long *)0xF1010018)
#define GPIODOH *((volatile unsigned long *)0xF1010140)
#define GPIODOECH *((volatile unsigned long *)0xF1010144)
void setup_window() {
*((volatile unsigned long *)0xD0020080) = 0xF1000000;
}
void cstart(void)
{
int i;
MPPCTL6 &= 0xffffff0f; /* set mpp49 as GPIO */
GPIODOECH &= 0xfffdffff ; /* set GPIO49 as output */
while (1) {
GPIODOH ^= 0x00020000; /* toggle GPIO49 state */
for (i = 0; i < delay; i++); /* wait */
}
}
- ldscript
SECTIONS
{
. = 0x15000000;
}
- Makefile
bare.bin: bare.elf
objcopy -O binary $> $@
bare.elf: init.S main.c
${CC} -g -Wall -nostdlib $> -o $@ -T ldscript
Cette commande devrait compiler l'ensemble :
PATH=/usr/cross/sheeva/usr/arm-unknown-openbsd`uname -r`/bin:$PATH make
Maintenant branchez le sheevaplug, et lancez OpenOCD depuis le repertoire contenant les binaires juste produits.
reset halt load_image bare.elf resume 0x15000000
Normalement, la LED du sheevaplug devrait clignoter.
Datasheets
Dans la mesure du possible, épluchez un peu ces docs avant le trail.
- hardware 88f6281
- programmation du 88f6281
- reference design du sheevaplug
- schemas du sheevaplug
- manuel de reference ARMv5 ATTENTION, enregistrement nécessaire.

