Niklaus Giger wrote: > Am Donnerstag, 14. Dezember 2006 14:14 schrieb Jan Kiszka: >> Niklaus Giger wrote: >>> Hi >>> >>> To document basic Xenomai/Linux patterns I developed the attached small >>> example for our PPC405 board, which just rolls the 8 debug LEDs. >>> >>> Are there any comments about it? >> I like the idea of having useful generic code patterns like this in the >> examples repos. But I also have a few wishes regarding this particular one: >> >> * I would prefer that generic patterns are coded against POSIX or maybe >> Native, not against a special RTOS skin (not everyone know the >> VxWorks API by heart ;) ). >> >> * Try to make use of as less additional patterns beyond the core aspect >> as possible. E.g., running the lights in main would avoid quite some >> code for init/cleanup. This helps the reader to grab the essence of >> the demo. Still, the demo should remain functional! > I used the Linux "sleep" function and could eliminate all RT specifics and it > still runs, albeit five times slower on my target.
You could replace sleep() with absolute clock_nanosleep(), kill the printfs, do an appropriate pthread_setschedparam() on init, and you would allow to gain determinism again by linking against the POSIX skin. >> * Please format your code according to kernel style (could be any >> style, but we need a standard, so pick that one) > Tried, using Documentation/CodingStyle from the kernel. Hope I didn't miss to > many thinks Just a few +80 char lines and some not-yet-tabs indentions. >>> Shall I put it into the Wiki at http://www.xenomai.org/index.php/Examples >>> or does somebody want to commit it to the examples part of the subversion >>> trunk? >> I would happily merge a cleaned up version into the repos, e.g. under >> the related skin. > I hope the attached version satisfy you now. Also added some suggestions made > by Stephan Fillod. Almost :). Find comments below. > >> PS: If you want to contribute VxWorks-specific code pattern, you are >> welcome as well! > Will come to this a little bit later, as I making good progress to port our > existing vxWorks application over to Xenomai. In any case, there is > ksrc/skins/vxworks/demos/satch.c and the the simulator testsuite under > sim/skins/vxworks/testsuite/. But if you open for each skin a directory (what > could be a good idea) one could add a README pointing to it. The idea is that those demos get migrated to examples over the time to let us focus on one repository. If there are some sim-tests that can serve as examples as well, they could be copied and adopted. Once someone posts the first vxworks code for inclusion (e.g. a reformatted and commented existing demo), I'm going to create a new dir and push it in. Again: all examples should focus on one core idea (one for simple periodic tasks, one for message queues, ...). > > Best regards > > > > ------------------------------------------------------------------------ > > /* > * This small examples shows how to access memory directly. > * > * Copyright (c) 2006 Niklaus Giger <niklaus.giger at member.fsf.org> > * > * It will only work on PPC405GPr based custom HW board of Nestal Maschinen AG > * > * It should, however, be easily adapted to similar HW > * It will scroll across 8 LEDs (interval 1/2 of second), which are mapped > * to some bit of the GPIO of the PPC405GPr processor. > * To sleep it uses the Linux sleep a second, so do not expect a real time > behaviour. See above. > * Compile it with at least -O to expand the inline assembler code. > * > * You may find another example at http://www.denx.de/wiki/bin/view/\ > * PPCEmbedded/DeviceDrivers#Section_AccessingPeripheralsFromUserSpace > * Wherefrom we stole the out_32 and iounmap procedures. > * > * Fillod Stephane recommends: > * "Personally, I always access hardware registers through in_[lbe]{8,16,32} > * "out_[lbe]{8,16,32} macros, so the code is portable across machines of > * "different endianess, and thanks to the integrated memory barriers, > * "I known exactly when the CPU will actually perform the I/O with respect > * "to the other C instructions." > * These macros are defined e.g. asm-ppc/io.h, but only available to the > kernel This is a user-space demo, right? In what way can the comment above help the reader then? Might rather cause confusions. > * > */ > > #include <stdio.h> > #include <fcntl.h> > #include <stdlib.h> > #include <unistd.h> > #include <sys/mman.h> > #include <unistd.h> > > void *mapDirectIoRegister(unsigned long addr, size_t length); > int iounmap(volatile void *start, size_t length); > void sysLedSet(unsigned char value); Not needed. > > #define MAP_SIZE 4096UL > #define MAP_MASK (MAP_SIZE - 1) > #define HCU3_LED_REGISTER 0xEF600700 > > volatile unsigned long *ledRegister; > > #ifdef __PPC__ > extern inline void out_32(volatile unsigned long *addr, unsigned val) > { > __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" > (val)); Maybe some explanation on this code would be helpful. It contains a memory barrier, right? The user should find a notice that other arch /may/ require barriers as well. > } > /* etc., cf asm/io.h */ > #else > extern inline void out_32(volatile unsigned long *addr, unsigned val) > { * which shows you how to use PPC assembler code to ensure correct IO > ordering. ??? > > *addr = val & 0xff; ???? > } > #endif > > void *mapDirectIoRegister(unsigned long addr, size_t length) > { > void *map_base, * virtAddr; > off_t target = ((unsigned int) addr) & ~MAP_MASK; > int fd; > > if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { > printf("/dev/mem could not be opened.\n"); > exit(1); > } > > // Map one page /* */ please. > map_base = mmap((void *)target, length, PROT_READ | PROT_WRITE, > MAP_SHARED, > fd, target); > if(map_base == (void *) -1) { > printf("Memory map failed for address 0x%lx\n", addr); > return map_base; > } > > virtAddr = (void *) ((unsigned long)map_base + ( (unsigned long)addr & > MAP_MASK)); > printf("Memory map 0x%lx -> %p offset 0x%lx virtual %p\n", addr, > map_base, > addr & MAP_MASK, virtAddr); > return virtAddr; > } > > int iounmap(volatile void *start, size_t length) > { > unsigned long ofs_addr; > ofs_addr = (unsigned long)start & (getpagesize()-1); > > /* do some cleanup when you're done with it */ > return munmap((void*)start-ofs_addr, length+ofs_addr); > } > > void sysLedSet(unsigned char value) > { > /* For obscure HW reasons, we have to negated it and shift the value 23 > bits to the left */ Means: on your specific board? Please make this explicit. > *ledRegister = (( unsigned long ) ~value << 23) ; > out_32(ledRegister, ( unsigned long ) ~value << 23); > } > > int main (int argc, char *argv[]) > { > unsigned char j; > printf("%s: %s %s\n", __FUNCTION__, __DATE__, __TIME__ ); > > /* HW initialisation */ > ledRegister = (unsigned long > *)mapDirectIoRegister(HCU3_LED_REGISTER, MAP_SIZE); > /* next we set the correct control mask in the GPIO_TCR */ > ledRegister[1] = 0x7ffe0000; /* Three State Control */ > > /* Now scroll our leds and pause a little bit between */ > for (j=0; j <= 8; j++) { > sleep(1); > printf("."); fflush(stdout); > sysLedSet(1 << j); > } > iounmap((volatile void *)HCU3_LED_REGISTER, MAP_SIZE); > printf("\n%s:done\n", __FUNCTION__); > return 0; > } Thanks again, Jan
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Xenomai-help mailing list [email protected] https://mail.gna.org/listinfo/xenomai-help
