* [Xenomai-help] RTDM driver structure
@ 2010-08-05 2:49 Bob Feretich
2010-08-05 7:07 ` Gilles Chanteperdrix
0 siblings, 1 reply; 16+ messages in thread
From: Bob Feretich @ 2010-08-05 2:49 UTC (permalink / raw)
To: xenomai
I want to verify that my understanding of the RTDM driver structure is
correct.
My driver is created as a module that is loaded by Linux insmod. Given
that...
My module_init routine (and module_exit)...
* is executed in the Linux driver context.
* should use Linux spin locks and events instead of rt_locks and events.
* can call rtdm_irq_request (rtrm_irq_free) to register my interrupt
handlers
for rt interrupts.
* can call rtdm_device_register (rt_dm_device_unregister) to register
my rt device.
* can call Linux omap dm_timer routines to reserve general purpose timers,
so that Linux will not give my timers to others. (these routines
call Linux locks)
My driver's open_nrt close_nrt entry points... (open_rt & close_rt are
deprecated)
* are executed in the caller's Linux user context, if the caller is a
standard Linux
user process.
* are executed in the caller's Xenomai user context (secondary mode),
if the caller
is a rt user process.
* can use Linux spin locks and events instead of rt_locks and events,
if I know
that protection is not needed from rt tasks and interrupt handlers.
* should use rt locks and events, if protection is needed from rt tasks
and
interrupt handlers.
My driver's ioctl_rt, read_rt, and write_rt entry points...
* are executed in the caller's Xenomai user context (primary mode), if
the caller
is a rt user process running in primary mode.
* are executed in the caller's Xenomai user context (secondary mode),
if the caller
is a rt user process running in secondary mode.
* must use rt locks and events.
My driver's ioctl_nrt, read_nrt, and write_nrt entry points...
* are executed in the caller's Linux user context, if the caller is a
standard
Linux user process.
* I should use rt locks and events, for protection from rt tasks and
interrupt handlers.
My driver's rt interrupt handler entry points...
* are executed in the Xenomai interrupt context.
* must use rt locks and events.
Is the above correct?
The OMAP3 chip has a collection of hardware timers that must be shared
between the Linux and Xenomai environments. I want to allocate/reserve 5
timers for my use in the real time environment for the creation of pulse
width modulation output signals, but the rest of the timers should be
available for general Linux use. Being able to call omap dm_timer
routines in the module_init and module_exit routines make this much easier.
Regards,
Bob Feretich
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [Xenomai-help] RTDM driver structure 2010-08-05 2:49 [Xenomai-help] RTDM driver structure Bob Feretich @ 2010-08-05 7:07 ` Gilles Chanteperdrix 2010-08-05 18:57 ` Bob Feretich 2010-08-07 2:22 ` [Xenomai-help] RTDM driver structure - an update Bob Feretich 0 siblings, 2 replies; 16+ messages in thread From: Gilles Chanteperdrix @ 2010-08-05 7:07 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Bob Feretich wrote: > I want to verify that my understanding of the RTDM driver structure is > correct. > > My driver is created as a module that is loaded by Linux insmod. Given > that... > > My module_init routine (and module_exit)... > * is executed in the Linux driver context. > * should use Linux spin locks and events instead of rt_locks and events. > * can call rtdm_irq_request (rtrm_irq_free) to register my interrupt > handlers > for rt interrupts. > * can call rtdm_device_register (rt_dm_device_unregister) to register > my rt device. > * can call Linux omap dm_timer routines to reserve general purpose timers, > so that Linux will not give my timers to others. (these routines > call Linux locks) > > My driver's open_nrt close_nrt entry points... (open_rt & close_rt are > deprecated) > * are executed in the caller's Linux user context, if the caller is a > standard Linux > user process. > * are executed in the caller's Xenomai user context (secondary mode), > if the caller > is a rt user process. > * can use Linux spin locks and events instead of rt_locks and events, > if I know > that protection is not needed from rt tasks and interrupt handlers. > * should use rt locks and events, if protection is needed from rt tasks > and > interrupt handlers. > > My driver's ioctl_rt, read_rt, and write_rt entry points... > * are executed in the caller's Xenomai user context (primary mode), if > the caller > is a rt user process running in primary mode. > * are executed in the caller's Xenomai user context (secondary mode), > if the caller > is a rt user process running in secondary mode. > * must use rt locks and events. > > My driver's ioctl_nrt, read_nrt, and write_nrt entry points... > * are executed in the caller's Linux user context, if the caller is a > standard > Linux user process. > * I should use rt locks and events, for protection from rt tasks and > interrupt handlers. > > My driver's rt interrupt handler entry points... > * are executed in the Xenomai interrupt context. > * must use rt locks and events. > > Is the above correct? Hi, Yes, this is correct. Note however, that if you need to lock something in the init_module or an nrt callback, and you use a linux lock, you will not be able to use this lock from rt context, so, the only way to solve this will be to use an rtdm lock. > > The OMAP3 chip has a collection of hardware timers that must be shared > between the Linux and Xenomai environments. I want to allocate/reserve 5 > timers for my use in the real time environment for the creation of pulse > width modulation output signals, but the rest of the timers should be > available for general Linux use. Being able to call omap dm_timer > routines in the module_init and module_exit routines make this much easier. Another remark: Xenomai uses, as, a system timer, a timer in one-shot mode (same as Linux so-called "high resolution timers"), so, if you program several periodic software timers, Xenomai timer subsystem will arrange for your timer callbacks to be called at the right time, so it looks like you will not gain much by using several hardware timers. If you fear that Xenomai timing subsystem will not scale well with many timers, you can enable the heap-based or wheel-based timer management. Regards. -- Gilles. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure 2010-08-05 7:07 ` Gilles Chanteperdrix @ 2010-08-05 18:57 ` Bob Feretich 2010-08-05 19:27 ` Gilles Chanteperdrix 2010-08-07 2:22 ` [Xenomai-help] RTDM driver structure - an update Bob Feretich 1 sibling, 1 reply; 16+ messages in thread From: Bob Feretich @ 2010-08-05 18:57 UTC (permalink / raw) To: Gilles Chanteperdrix, xenomai Comments inline... On 8/5/2010 12:07 AM, Gilles Chanteperdrix wrote: > > Another remark: Xenomai uses, as, a system timer, a timer in one-shot > mode (same as Linux so-called "high resolution timers"), so, if you > program several periodic software timers, Xenomai timer subsystem will > arrange for your timer callbacks to be called at the right time, so it > looks like you will not gain much by using several hardware timers. If > you fear that Xenomai timing subsystem will not scale well with many > timers, you can enable the heap-based or wheel-based timer management. The GPTimers that I am using have special hardware that drives pins on the chip. They can be programmed to create waveforms of specific pulse width and period and auto-restart so that the pulse train is continuous. Software only gets involved when the pulse width or period needs to be changed. If I used the Xenomai timer, software (to change the state of a GPIO pin) would be invoked every time any of these signals needed to transition. Using the hardware timers for the generation pulse trains of fixed pulse width and period takes zero CPU cycles. Regards, Bob ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure 2010-08-05 18:57 ` Bob Feretich @ 2010-08-05 19:27 ` Gilles Chanteperdrix 0 siblings, 0 replies; 16+ messages in thread From: Gilles Chanteperdrix @ 2010-08-05 19:27 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Bob Feretich wrote: > Comments inline... > > On 8/5/2010 12:07 AM, Gilles Chanteperdrix wrote: >> Another remark: Xenomai uses, as, a system timer, a timer in one-shot >> mode (same as Linux so-called "high resolution timers"), so, if you >> program several periodic software timers, Xenomai timer subsystem will >> arrange for your timer callbacks to be called at the right time, so it >> looks like you will not gain much by using several hardware timers. If >> you fear that Xenomai timing subsystem will not scale well with many >> timers, you can enable the heap-based or wheel-based timer management. > The GPTimers that I am using have special hardware that drives pins on > the chip. They can be programmed to create waveforms of specific pulse > width and period and auto-restart so that the pulse train is continuous. > Software only gets involved when the pulse width or period needs to be > changed. If I used the Xenomai timer, software (to change the state of > a GPIO pin) would be invoked every time any of these signals needed to > transition. > > Using the hardware timers for the generation pulse trains of fixed pulse > width and period takes zero CPU cycles. Ok. Understood, the software could not even reloead the registers fast enough. -- Gilles. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-05 7:07 ` Gilles Chanteperdrix 2010-08-05 18:57 ` Bob Feretich @ 2010-08-07 2:22 ` Bob Feretich 2010-08-08 9:36 ` Everett Wang 1 sibling, 1 reply; 16+ messages in thread From: Bob Feretich @ 2010-08-07 2:22 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai I completed porting my PWM timer driver to Xenomai. I limited the heavy use of the dm_timer routines to the module_init and module_exit routines. Other parts of the driver only used the dm_timer routines that read and wrote timer registers. You guys did a great job defining and implementing Xenomai and RTDM. Porting the Linux driver to RTDM was easy (2 days). It worked the first time I got a clean compile! I have 4 pulse width modulated signals being output by the OMAP3 chip, 3 are completely generated by hardware, the other is done by software being activated by RT interrupts. When I examined the signals with a scope, I couldn't tell which one was software generated. In the pure Linux environment I was seeing 100-200 microseconds of jitter on the software generated signal on a lightly loaded system. Under the same conditions in Xenomai, there was no noticeable jitter. Thanks for your help. Regards, Bob Feretich On 8/5/2010 12:07 AM, Gilles Chanteperdrix wrote: > Bob Feretich wrote: >> I want to verify that my understanding of the RTDM driver structure is >> correct. >> >> My driver is created as a module that is loaded by Linux insmod. Given >> that... >> >> My module_init routine (and module_exit)... >> * is executed in the Linux driver context. >> * should use Linux spin locks and events instead of rt_locks and events. >> * can call rtdm_irq_request (rtrm_irq_free) to register my interrupt >> handlers >> for rt interrupts. >> * can call rtdm_device_register (rt_dm_device_unregister) to register >> my rt device. >> * can call Linux omap dm_timer routines to reserve general purpose timers, >> so that Linux will not give my timers to others. (these routines >> call Linux locks) >> >> My driver's open_nrt close_nrt entry points... (open_rt& close_rt are >> deprecated) >> * are executed in the caller's Linux user context, if the caller is a >> standard Linux >> user process. >> * are executed in the caller's Xenomai user context (secondary mode), >> if the caller >> is a rt user process. >> * can use Linux spin locks and events instead of rt_locks and events, >> if I know >> that protection is not needed from rt tasks and interrupt handlers. >> * should use rt locks and events, if protection is needed from rt tasks >> and >> interrupt handlers. >> >> My driver's ioctl_rt, read_rt, and write_rt entry points... >> * are executed in the caller's Xenomai user context (primary mode), if >> the caller >> is a rt user process running in primary mode. >> * are executed in the caller's Xenomai user context (secondary mode), >> if the caller >> is a rt user process running in secondary mode. >> * must use rt locks and events. >> >> My driver's ioctl_nrt, read_nrt, and write_nrt entry points... >> * are executed in the caller's Linux user context, if the caller is a >> standard >> Linux user process. >> * I should use rt locks and events, for protection from rt tasks and >> interrupt handlers. >> >> My driver's rt interrupt handler entry points... >> * are executed in the Xenomai interrupt context. >> * must use rt locks and events. >> >> Is the above correct? > Hi, > > Yes, this is correct. Note however, that if you need to lock something > in the init_module or an nrt callback, and you use a linux lock, you > will not be able to use this lock from rt context, so, the only way to > solve this will be to use an rtdm lock. > >> The OMAP3 chip has a collection of hardware timers that must be shared >> between the Linux and Xenomai environments. I want to allocate/reserve 5 >> timers for my use in the real time environment for the creation of pulse >> width modulation output signals, but the rest of the timers should be >> available for general Linux use. Being able to call omap dm_timer >> routines in the module_init and module_exit routines make this much easier. > Another remark: Xenomai uses, as, a system timer, a timer in one-shot > mode (same as Linux so-called "high resolution timers"), so, if you > program several periodic software timers, Xenomai timer subsystem will > arrange for your timer callbacks to be called at the right time, so it > looks like you will not gain much by using several hardware timers. If > you fear that Xenomai timing subsystem will not scale well with many > timers, you can enable the heap-based or wheel-based timer management. > > Regards. > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-07 2:22 ` [Xenomai-help] RTDM driver structure - an update Bob Feretich @ 2010-08-08 9:36 ` Everett Wang 2010-08-08 12:08 ` Gilles Chanteperdrix 2010-08-10 0:56 ` Bob Feretich 0 siblings, 2 replies; 16+ messages in thread From: Everett Wang @ 2010-08-08 9:36 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Hi Bob, Great job. :-D Do you have plan to port SPI to RTDM? Last time when I checked the rs232 driver in RTDM for omap3 still also had problem. I don't mind to work on that. But I am driver-challenged person. Have a nice weekend. Everett On Sat, Aug 7, 2010 at 10:22 AM, Bob Feretich <bob.feretich@domain.hid> wrote: > I completed porting my PWM timer driver to Xenomai. > I limited the heavy use of the dm_timer routines to the module_init and > module_exit routines. Other parts of the driver only used the dm_timer > routines that read and wrote timer registers. > > You guys did a great job defining and implementing Xenomai and RTDM. > Porting the Linux driver to RTDM was easy (2 days). It worked the first > time I got a clean compile! > > I have 4 pulse width modulated signals being output by the OMAP3 chip, 3 > are completely generated by hardware, the other is done by software > being activated by RT interrupts. When I examined the signals with a > scope, I couldn't tell which one was software generated. In the pure > Linux environment I was seeing 100-200 microseconds of jitter on the > software generated signal on a lightly loaded system. Under the same > conditions in Xenomai, there was no noticeable jitter. > > Thanks for your help. > Regards, > Bob Feretich > > On 8/5/2010 12:07 AM, Gilles Chanteperdrix wrote: >> Bob Feretich wrote: >>> I want to verify that my understanding of the RTDM driver structure is >>> correct. >>> >>> My driver is created as a module that is loaded by Linux insmod. Given >>> that... >>> >>> My module_init routine (and module_exit)... >>> * is executed in the Linux driver context. >>> * should use Linux spin locks and events instead of rt_locks and events. >>> * can call rtdm_irq_request (rtrm_irq_free) to register my interrupt >>> handlers >>> for rt interrupts. >>> * can call rtdm_device_register (rt_dm_device_unregister) to register >>> my rt device. >>> * can call Linux omap dm_timer routines to reserve general purpose timers, >>> so that Linux will not give my timers to others. (these routines >>> call Linux locks) >>> >>> My driver's open_nrt close_nrt entry points... (open_rt& close_rt are >>> deprecated) >>> * are executed in the caller's Linux user context, if the caller is a >>> standard Linux >>> user process. >>> * are executed in the caller's Xenomai user context (secondary mode), >>> if the caller >>> is a rt user process. >>> * can use Linux spin locks and events instead of rt_locks and events, >>> if I know >>> that protection is not needed from rt tasks and interrupt handlers. >>> * should use rt locks and events, if protection is needed from rt tasks >>> and >>> interrupt handlers. >>> >>> My driver's ioctl_rt, read_rt, and write_rt entry points... >>> * are executed in the caller's Xenomai user context (primary mode), if >>> the caller >>> is a rt user process running in primary mode. >>> * are executed in the caller's Xenomai user context (secondary mode), >>> if the caller >>> is a rt user process running in secondary mode. >>> * must use rt locks and events. >>> >>> My driver's ioctl_nrt, read_nrt, and write_nrt entry points... >>> * are executed in the caller's Linux user context, if the caller is a >>> standard >>> Linux user process. >>> * I should use rt locks and events, for protection from rt tasks and >>> interrupt handlers. >>> >>> My driver's rt interrupt handler entry points... >>> * are executed in the Xenomai interrupt context. >>> * must use rt locks and events. >>> >>> Is the above correct? >> Hi, >> >> Yes, this is correct. Note however, that if you need to lock something >> in the init_module or an nrt callback, and you use a linux lock, you >> will not be able to use this lock from rt context, so, the only way to >> solve this will be to use an rtdm lock. >> >>> The OMAP3 chip has a collection of hardware timers that must be shared >>> between the Linux and Xenomai environments. I want to allocate/reserve 5 >>> timers for my use in the real time environment for the creation of pulse >>> width modulation output signals, but the rest of the timers should be >>> available for general Linux use. Being able to call omap dm_timer >>> routines in the module_init and module_exit routines make this much easier. >> Another remark: Xenomai uses, as, a system timer, a timer in one-shot >> mode (same as Linux so-called "high resolution timers"), so, if you >> program several periodic software timers, Xenomai timer subsystem will >> arrange for your timer callbacks to be called at the right time, so it >> looks like you will not gain much by using several hardware timers. If >> you fear that Xenomai timing subsystem will not scale well with many >> timers, you can enable the heap-based or wheel-based timer management. >> >> Regards. >> > > _______________________________________________ > Xenomai-help mailing list > Xenomai-help@domain.hid > https://mail.gna.org/listinfo/xenomai-help > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-08 9:36 ` Everett Wang @ 2010-08-08 12:08 ` Gilles Chanteperdrix 2010-08-08 14:32 ` Everett Wang 2010-08-10 0:56 ` Bob Feretich 1 sibling, 1 reply; 16+ messages in thread From: Gilles Chanteperdrix @ 2010-08-08 12:08 UTC (permalink / raw) To: Everett Wang; +Cc: xenomai, Bob Feretich Everett Wang wrote: > Hi Bob, > > Great job. :-D Do you have plan to port SPI to RTDM? Last time when I > checked the rs232 driver > in RTDM for omap3 still also had problem. I don't mind to work on > that. But I am driver-challenged person. If you are referring to the problem described here: https://mail.gna.org/public/xenomai-help/2010-05/msg00166.html Wolfgang answered here: https://mail.gna.org/public/xenomai-help/2010-05/msg00167.html If you are referring to another problem, it would be nice to receive a real bug report, not just "omap3 has problems". -- Gilles. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-08 12:08 ` Gilles Chanteperdrix @ 2010-08-08 14:32 ` Everett Wang 0 siblings, 0 replies; 16+ messages in thread From: Everett Wang @ 2010-08-08 14:32 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai, Bob Feretich On Sun, Aug 8, 2010 at 8:08 PM, Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org> wrote: > Everett Wang wrote: >> Hi Bob, >> >> Great job. :-D Do you have plan to port SPI to RTDM? Last time when I >> checked the rs232 driver >> in RTDM for omap3 still also had problem. I don't mind to work on >> that. But I am driver-challenged person. > > If you are referring to the problem described here: > https://mail.gna.org/public/xenomai-help/2010-05/msg00166.html > Wolfgang answered here: > https://mail.gna.org/public/xenomai-help/2010-05/msg00167.html > > If you are referring to another problem, it would be nice to receive a > real bug report, not just "omap3 has problems". > > -- > Gilles. > Hi Gilles, Sorry that I was not clear on the rs232 for omap3. I encountered a problem when I tried to run cross-link example for beagle-board on xenomai 2.5.3. Wolfgang helped me for compiling and loading the xeno_16550A.ko driver for rts0 and rts1. That was resolved successfully. But I still couldn't make cross-link example to run. Wolfgang mentioned a potential problem in regshift for omap3. This what he said: quote Wolfgang Grandegger to me, xenomai-help show details May 26 ..... Next I would try to load the xeno_16550a.ko as described earlier. Then you need to fix the register access by introducing a proper regshift, at least. I can't tell if other fixups are necessary but if you are lucky it will already work. And yes, implementing a RTDM SPI driver is even harder, unfortunately. Wolfgang. end of quote. I can't get the mail link from our mailing list since google groups were blocked inside of China. :-( Everett ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-08 9:36 ` Everett Wang 2010-08-08 12:08 ` Gilles Chanteperdrix @ 2010-08-10 0:56 ` Bob Feretich 2010-08-10 7:43 ` Guenter Ebermann 2010-08-10 13:18 ` Gilles Chanteperdrix 1 sibling, 2 replies; 16+ messages in thread From: Bob Feretich @ 2010-08-10 0:56 UTC (permalink / raw) To: Everett Wang; +Cc: xenomai I am porting the the ADIS SPI driver now. The GPIO interrupt problem that I reported is from the Data Ready interrupt from the sensor. The OMAP3 chip has 6 GPIO interrupt modules. Each module merges 32 GPIO interrupt channels (1 channel per GPIO pin). Interrupts on these channels can be routed to either the ARM MPU or to the graphics subsystem (IVA). Only the channels that are mapped to the MPU are of interest to Adeos. MPU_IRQ GPIO_module GPIO_pins_in_module IRQ29 GPIO1 31-0 IRQ30 GPIO2 63-34,33,32 IRQ31 GPIO3 95-83,82,81,80,79-64 IRQ32 GPIO4 127,126-96 IRQ33 GPIO5 159-128 IRQ34 GPIO6 191-160 The breaks in the above ranges indicate slightly different capabilities. A signal change on any GPIO pin can cause an interrupt to occur for the group. There are several 32-bit control registers (discussed below) associated with each group. The bits in the control registers are mapped one to one with the interrupt channels of the group. The Linux interrupt handler receives the IRQ 29-34 GPIO_module interrupts, determines which channel caused it and calls the interrupt handler associated with that channel by mapping the interrupt to an IRQ in the IRQ 160 to 351 range. (These IRQs don't go through the twl family chips.) The below registers should be used by Adeos to detect and process interrupts: GPIOn_IRQSTATUS1 GPIOn_IRQENABLE1 aliases (GPIO_SETIRQENABLE1, GPIOn_CLEARIRQENABLE1) The below registers need to be configured by the driver, to tell the hardware when to initiate an interrupt: GPIOn_LEVELDETECT0 (0x1: enable the IRQ assertion on low level detect) GPIOn_LEVELDETECT1 (0x1: enable the IRQ assertion on high level detect) GPIOn_RISINGDETECT (0x1: enable IRQ/Wakeup on rising edge detect) GPIOn_FALLINGDETECT (0x1: enable IRQ/Wakeup on falling edge detect) All the bits in the above xxxDETECT registers are set to zeroes at processor initialization. If they remain zero, all GPIO Channel interrupts are effectively disabled. I'm sure this is what is occurring in my situation. For standard Linux drivers, I configure the xxxDETECT registers by setting flags in the request_irq() call. These flags are not present in the rtdm_irq_request() parameters. There is a RTDM_IRQTYPE_EDGE flag, but there is no description of what it does or when to use it. It is not sufficient to determine the settings of the xxxDETECT registers. Also, the documentation is not clear whether an IRQ requested via rtdm_irq_request() is initially enabled or disabled (disabled would be better). Setting values in the xxxDETECT registers has a scope that effects any driver listening to that IRQ (both Xenomai and Linux). In this case, it is appropriate that I request/reserve the IRQ in both environments and hold my reservation in both environments until my driver is unloaded. I can then configure these registers via my call to request_irq(). First, I will request the GPIO Channel IRQ in Linux, but keep it disabled. Then, I will request it in Xenomai via rtdm_irq_request(). Then enable the IRQ only in Xenomai. Will that screw up the IRQs handling in the Adeos pipe? I assume that Adeos can handle interrupts occurring on either or both edges. How should I set the flags on the rtdm_irq_request()? Do the flags in an active request_irq() have an effect on a subsequent rtdm_irq_request()? Do I need to mark the IRQ SHARED in the request_irq()? Does executing a rtdm_irq_request(), without the SHARED flag, fail if the IRQ was reserved via request_irq()? (The purpose of the flag is not documented in the API manual.) Do I need to specify the SHARED flag in both request_irq() and rtdm_irq_request()? I'd rather not allow any other driver access to my IRQ. Per Gilles comment, Linux should not allow me to execute a "set_irq_type" without holding a reservation to the IRQ. And, if I am holding the reservation, then I could have configured the irq type via the request_irq(). Regards, Bob On 8/8/2010 2:36 AM, Everett Wang wrote: > Hi Bob, > > Great job. :-D Do you have plan to port SPI to RTDM? Last time when I > checked the rs232 driver > in RTDM for omap3 still also had problem. I don't mind to work on > that. But I am driver-challenged person. > > Have a nice weekend. > > Everett > > On Sat, Aug 7, 2010 at 10:22 AM, Bob Feretich > <bob.feretich@domain.hid> wrote: >> ...snipped ... >> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 0:56 ` Bob Feretich @ 2010-08-10 7:43 ` Guenter Ebermann 2010-08-10 9:08 ` Bob Feretich 2010-08-10 13:18 ` Gilles Chanteperdrix 1 sibling, 1 reply; 16+ messages in thread From: Guenter Ebermann @ 2010-08-10 7:43 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Hi Bob, Am 10.08.2010 um 02:56 schrieb Bob Feretich: > Do I need to mark the IRQ SHARED in the request_irq()? > Does executing a rtdm_irq_request(), without the SHARED flag, fail if > the IRQ was reserved via request_irq()? (The purpose of the flag is not > documented in the API manual.) > Do I need to specify the SHARED flag in both request_irq() and > rtdm_irq_request()? I'd rather not allow any other driver access to my IRQ. I am relatively new to xenomai, but perhaps I can shed some light on shared IRQs: Shared IRQs are used if more than one device share one interrupt line. E.g.: Two PCI cards use the same interrupt line. The cards output has high-resistance if the interrupt is disabled. A external pull-up is used. So if no interrupt is pending the voltage is high on the line. The interrupt must also be level sensitive. Whenever a interrupt occurs one card pulls down the IRQ line to ground. This also works if both cards pull the IRQ down the same time (IRQ happens at the same time). Also the return value of the IRQ is important if the IRQ is shared. The first thing you have to do is check if it was your device that issued the irq (by accessing some registers in your device). If it was your device do what has to be done (ack the interrupt in the device so that it doesnt pull down the level to ground any more) and return IRQ_HANDLED. If its not your return IRQ_NO_HANDLED or such. So if you write a driver for one of this two cards you must use the IRQ_SHARED flag (this is the same with standard linux interrupt API - just call request_irq with irqflags=IRQF_SHARED) so that linux knows that after it calls your handler it must also call all other handlers of this IRQ. However shared IRQs can be used for all kind of devices. But PCI is the only example I am aware of where it really is used. It is also the root of alot of problems because one must be really careful to handle such shared IRQs correctly. So its more likely your device does not use shared IRQs. But perhaps in xenomai API this flag means a different thing I am not yet aware of. Kind regards, Guenter ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 7:43 ` Guenter Ebermann @ 2010-08-10 9:08 ` Bob Feretich 2010-08-10 13:33 ` Gilles Chanteperdrix 0 siblings, 1 reply; 16+ messages in thread From: Bob Feretich @ 2010-08-10 9:08 UTC (permalink / raw) To: Guenter Ebermann; +Cc: xenomai Gunther, Thank you for the information. No, the my hardware interrupt line is not being shared by other devices. So I really don't want it to be considered "shared". However, my concern was on how driver IRQ request calls are handled. If a driver invokes request_irq() without the SHARED flag, I would expect Linux to reject subsequent request_irq() calls for the same IRQ made by other drivers. Similarly, if the first driver invokes request_irq() with the SHARED flag, I would expect Linux to accept subsequent request_irq() calls for the same IRQ made by other drivers if-and-only-if the other requests are made with the SHARED flag. My temporary fix for the problem I encountered required me to request the same IRQ from Linux via request_irq() and then from Xenomai via rtdm_irq_request(). I had expected the Xenomai request to fail. However, that expectation assumed that there are interlocks between the environments. I perceived problems in either case. If there are no interlocks, then both a real-time driver and a non-real-time driver may be loaded to service the same IRQ and be ignorant of each other. This would probably be bad. If there are interlocks... Then for a non-shared IRQ, the first driver to request the IRQ would receive it. All other requestors, regardless of whether they are Xenomai or Linux would be refused. For a shared IRQ, the rules get much more complex. I believe that the first driver to request the IRQ would receive it, but if the driver specified the SHARED flag sharing would restricted the environment of that first driver. Requests made from the other environment should be rejected whether or not they specify SHARED. Since my temporary fix (requesting and receiving a non-shared IRQ in both the Linux and Xenomai environments) worked, if proved that there were no interlocks. Phillippe stated that this is a flaw in the current version of Xenomai. Regards, Bob On 8/10/2010 12:43 AM, Guenter Ebermann wrote: > Hi Bob, > > Am 10.08.2010 um 02:56 schrieb Bob Feretich: >> Do I need to mark the IRQ SHARED in the request_irq()? >> Does executing a rtdm_irq_request(), without the SHARED flag, fail if >> the IRQ was reserved via request_irq()? (The purpose of the flag is not >> documented in the API manual.) >> Do I need to specify the SHARED flag in both request_irq() and >> rtdm_irq_request()? I'd rather not allow any other driver access to my IRQ. > I am relatively new to xenomai, but perhaps I can shed some light on shared > IRQs: Shared IRQs are used if more than one device share one interrupt line. > E.g.: Two PCI cards use the same interrupt line. > > The cards output has high-resistance if the interrupt is disabled. A external > pull-up is used. So if no interrupt is pending the voltage is high on the line. > The interrupt must also be level sensitive. > > Whenever a interrupt occurs one card pulls down the IRQ line to ground. This > also works if both cards pull the IRQ down the same time (IRQ happens at the > same time). > > Also the return value of the IRQ is important if the IRQ is shared. The first > thing you have to do is check if it was your device that issued the irq (by > accessing some registers in your device). If it was your device do what has to > be done (ack the interrupt in the device so that it doesnt pull down the level > to ground any more) and return IRQ_HANDLED. If its not your return > IRQ_NO_HANDLED or such. > > So if you write a driver for one of this two cards you must use the IRQ_SHARED > flag (this is the same with standard linux interrupt API - just call > request_irq with irqflags=IRQF_SHARED) so that linux knows that after it calls > your handler it must also call all other handlers of this IRQ. > > However shared IRQs can be used for all kind of devices. But PCI is the only > example I am aware of where it really is used. It is also the root of alot of > problems because one must be really careful to handle such shared IRQs > correctly. > > So its more likely your device does not use shared IRQs. > > But perhaps in xenomai API this flag means a different thing I am not yet aware > of. > > Kind regards, > Guenter ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 9:08 ` Bob Feretich @ 2010-08-10 13:33 ` Gilles Chanteperdrix 2010-08-10 13:41 ` Philippe Gerum 0 siblings, 1 reply; 16+ messages in thread From: Gilles Chanteperdrix @ 2010-08-10 13:33 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Bob Feretich wrote: > Gunther, > Thank you for the information. > No, the my hardware interrupt line is not being shared by other devices. > So I really don't want it to be considered "shared". However, my concern > was on how driver IRQ request calls are handled. > > If a driver invokes request_irq() without the SHARED flag, I would > expect Linux to reject subsequent request_irq() calls for the same IRQ > made by other drivers. Similarly, if the first driver invokes > request_irq() with the SHARED flag, I would expect Linux to accept > subsequent request_irq() calls for the same IRQ made by other drivers > if-and-only-if the other requests are made with the SHARED flag. > > My temporary fix for the problem I encountered required me to request > the same IRQ from Linux via request_irq() and then from Xenomai via > rtdm_irq_request(). I had expected the Xenomai request to fail. However, > that expectation assumed that there are interlocks between the > environments. I perceived problems in either case. If there are no > interlocks, then both a real-time driver and a non-real-time driver may > be loaded to service the same IRQ and be ignorant of each other. This > would probably be bad. > > If there are interlocks... > Then for a non-shared IRQ, the first driver to request the IRQ would > receive it. All other requestors, regardless of whether they are Xenomai > or Linux would be refused. Ok. Adeos 101. Xenomai and Linux are living in different Adeos domains, each with its own interrupt handlers. The domains are organized in a pipeline. When an interrupt is received, it goes down the pipeline until a domain accepts it. The domain which accepts it may choose to propagate it or not to the next domain. So, there is nothing wrong with registering an interrupt handler for each domain. However, if the Xenomai domain interrupt handler decides not to propagate the interrupt to the Linux domain, Linux will simply never receive any interrupt. The SHARED flag applies to interrupts in the same domain, and are handled outside of the Adeos realm. The timer interrupt, on the other hand, propagates the interrupt when it sees fit, so that Linux timer handling is called. Both solutions are allowed. The reason why it is impossible to share an interrupt between two different drivers, unaware of each other, living in Xenomai and Linux domain is that it destroys the determinism. But even that can be made to work if we make a Xenomai domain driver for the Linux domain interrupt, aware of that Linux domain driver: https://mail.gna.org/public/xenomai-core/2008-07/msg00025.html > For a shared IRQ, the rules get much more complex. I believe that the > first driver to request the IRQ would receive it, but if the driver > specified the SHARED flag sharing would restricted the environment of > that first driver. Requests made from the other environment should be > rejected whether or not they specify SHARED. > Since my temporary fix (requesting and receiving a non-shared IRQ in > both the Linux and Xenomai environments) worked, if proved that there > were no interlocks. Phillippe stated that this is a flaw in the current > version of Xenomai. No, you misunderstood Philippe. What is a flaw in the current version of Xenomai is the fact that rtdm_request_irq does not configure the GPIO registers to set the GPIO interrupt to edge/level triggered, rising, falling, etc... The fact that the same interrupt can be requested in Xenomai domain and in Linux domain is perfectly normal, fits in the Adeos architecture, and is even needed for handling the timer interrupt on several architectures including arm. -- Gilles. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 13:33 ` Gilles Chanteperdrix @ 2010-08-10 13:41 ` Philippe Gerum 0 siblings, 0 replies; 16+ messages in thread From: Philippe Gerum @ 2010-08-10 13:41 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai, Bob Feretich On Tue, 2010-08-10 at 15:33 +0200, Gilles Chanteperdrix wrote: > Bob Feretich wrote: > > Gunther, > > Thank you for the information. > > No, the my hardware interrupt line is not being shared by other devices. > > So I really don't want it to be considered "shared". However, my concern > > was on how driver IRQ request calls are handled. > > > > If a driver invokes request_irq() without the SHARED flag, I would > > expect Linux to reject subsequent request_irq() calls for the same IRQ > > made by other drivers. Similarly, if the first driver invokes > > request_irq() with the SHARED flag, I would expect Linux to accept > > subsequent request_irq() calls for the same IRQ made by other drivers > > if-and-only-if the other requests are made with the SHARED flag. > > > > My temporary fix for the problem I encountered required me to request > > the same IRQ from Linux via request_irq() and then from Xenomai via > > rtdm_irq_request(). I had expected the Xenomai request to fail. However, > > that expectation assumed that there are interlocks between the > > environments. I perceived problems in either case. If there are no > > interlocks, then both a real-time driver and a non-real-time driver may > > be loaded to service the same IRQ and be ignorant of each other. This > > would probably be bad. > > > > If there are interlocks... > > Then for a non-shared IRQ, the first driver to request the IRQ would > > receive it. All other requestors, regardless of whether they are Xenomai > > or Linux would be refused. > > Ok. Adeos 101. > > Xenomai and Linux are living in different Adeos domains, each with its > own interrupt handlers. The domains are organized in a pipeline. When an > interrupt is received, it goes down the pipeline until a domain accepts > it. The domain which accepts it may choose to propagate it or not to the > next domain. So, there is nothing wrong with registering an interrupt > handler for each domain. However, if the Xenomai domain interrupt > handler decides not to propagate the interrupt to the Linux domain, > Linux will simply never receive any interrupt. > > The SHARED flag applies to interrupts in the same domain, and are > handled outside of the Adeos realm. > > The timer interrupt, on the other hand, propagates the interrupt when it > sees fit, so that Linux timer handling is called. Both solutions are > allowed. > > The reason why it is impossible to share an interrupt between two > different drivers, unaware of each other, living in Xenomai and Linux > domain is that it destroys the determinism. But even that can be made to > work if we make a Xenomai domain driver for the Linux domain interrupt, > aware of that Linux domain driver: > https://mail.gna.org/public/xenomai-core/2008-07/msg00025.html > > > For a shared IRQ, the rules get much more complex. I believe that the > > first driver to request the IRQ would receive it, but if the driver > > specified the SHARED flag sharing would restricted the environment of > > that first driver. Requests made from the other environment should be > > rejected whether or not they specify SHARED. > > Since my temporary fix (requesting and receiving a non-shared IRQ in > > both the Linux and Xenomai environments) worked, if proved that there > > were no interlocks. Phillippe stated that this is a flaw in the current > > version of Xenomai. > > No, you misunderstood Philippe. What is a flaw in the current version of > Xenomai is the fact that rtdm_request_irq does not configure the GPIO > registers to set the GPIO interrupt to edge/level triggered, rising, > falling, etc... The fact that the same interrupt can be requested in > Xenomai domain and in Linux domain is perfectly normal, fits in the > Adeos architecture, and is even needed for handling the timer interrupt > on several architectures including arm. Ack. > > -- Philippe. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 0:56 ` Bob Feretich 2010-08-10 7:43 ` Guenter Ebermann @ 2010-08-10 13:18 ` Gilles Chanteperdrix 2010-08-10 19:01 ` Bob Feretich 1 sibling, 1 reply; 16+ messages in thread From: Gilles Chanteperdrix @ 2010-08-10 13:18 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Bob Feretich wrote: > I am porting the the ADIS SPI driver now. The GPIO interrupt problem > that I reported is from the Data Ready interrupt from the sensor. > > The OMAP3 chip has 6 GPIO interrupt modules. Each module merges 32 GPIO > interrupt channels (1 channel per GPIO pin). Interrupts on these > channels can be routed to either the ARM MPU or to the graphics > subsystem (IVA). Only the channels that are mapped to the MPU are of > interest to Adeos. > MPU_IRQ GPIO_module GPIO_pins_in_module > IRQ29 GPIO1 31-0 > IRQ30 GPIO2 63-34,33,32 > IRQ31 GPIO3 95-83,82,81,80,79-64 > IRQ32 GPIO4 127,126-96 > IRQ33 GPIO5 159-128 > IRQ34 GPIO6 191-160 > The breaks in the above ranges indicate slightly different capabilities. > A signal change on any GPIO pin can cause an interrupt to occur for the > group. There are several 32-bit control registers (discussed below) > associated with each group. The bits in the control registers are mapped > one to one with the interrupt channels of the group. > > The Linux interrupt handler receives the IRQ 29-34 GPIO_module > interrupts, determines which channel caused it and calls the interrupt > handler associated with that channel by mapping the interrupt to an IRQ > in the IRQ 160 to 351 range. (These IRQs don't go through the twl family > chips.) > > The below registers should be used by Adeos to detect and process > interrupts: > GPIOn_IRQSTATUS1 > GPIOn_IRQENABLE1 aliases (GPIO_SETIRQENABLE1, GPIOn_CLEARIRQENABLE1) > > The below registers need to be configured by the driver, to tell the > hardware when to initiate an interrupt: > GPIOn_LEVELDETECT0 (0x1: enable the IRQ assertion on low level detect) > GPIOn_LEVELDETECT1 (0x1: enable the IRQ assertion on high level detect) > GPIOn_RISINGDETECT (0x1: enable IRQ/Wakeup on rising edge detect) > GPIOn_FALLINGDETECT (0x1: enable IRQ/Wakeup on falling edge detect) > All the bits in the above xxxDETECT registers are set to zeroes at > processor initialization. If they remain zero, all GPIO Channel > interrupts are effectively disabled. I'm sure this is what is occurring > in my situation. > > For standard Linux drivers, I configure the xxxDETECT registers by > setting flags in the request_irq() call. These flags are not present in > the rtdm_irq_request() parameters. > There is a RTDM_IRQTYPE_EDGE flag, but there is no description of what > it does or when to use it. It is not sufficient to determine the > settings of the xxxDETECT registers. The RTDM_IRQTYPE_EDGE is documented in RTDM API documentation: "Mark IRQ as edge-triggered, relevant for correct handling of shared edge-triggered IRQs. " Here: http://www.xenomai.org/documentation/xenomai-2.5/html/api/group__rtdmirq.html It does not cause the hardware to be configured, it just has an effect on what "flow handler" xenomai uses for this interrupt, in much the same way as set_irq_handler(irq, handle_edge_irq) for Linux interrupts. > Also, the documentation is not clear whether an IRQ requested via > rtdm_irq_request() is initially enabled or disabled (disabled would be > better). I would guess it is enabled, like when requesting one with request_irq. > > Setting values in the xxxDETECT registers has a scope that effects any > driver listening to that IRQ (both Xenomai and Linux). In this case, it > is appropriate that I request/reserve the IRQ in both environments and > hold my reservation in both environments until my driver is unloaded. I > can then configure these registers via my call to request_irq(). > First, I will request the GPIO Channel IRQ in Linux, but keep it disabled. > Then, I will request it in Xenomai via rtdm_irq_request(). > Then enable the IRQ only in Xenomai. > > Will that screw up the IRQs handling in the Adeos pipe? > I assume that Adeos can handle interrupts occurring on either or both edges. > > How should I set the flags on the rtdm_irq_request()? > Do the flags in an active request_irq() have an effect on a subsequent > rtdm_irq_request()? As explained by Philippe, rtdm_request_irq fails to do what request_irq does when xxxDETECT bits are set, or when you call set_irq_type. But you may be able to call set_irq_type for an IRQ registered with rtdm_request_irq (from reading the code, nothing seems to prevent it). Anyway, you can also call free_irq after request_irq and before rtdm_request_irq, the hardware registers will probably stay configured. > Do I need to mark the IRQ SHARED in the request_irq()? > Does executing a rtdm_irq_request(), without the SHARED flag, fail if > the IRQ was reserved via request_irq()? (The purpose of the flag is not > documented in the API manual.) > Do I need to specify the SHARED flag in both request_irq() and > rtdm_irq_request()? I'd rather not allow any other driver access to my IRQ. the rtdm_request_irq "SHARED" flag, works the same way as IRQF_SHARED for Linux interrupts. It means that Xenomai will be able to register several handlers for the same interrupt, much like Linux will be able to register several handlers with the SHARED flag. Its documentation is: "Enable IRQ-sharing with other real-time drivers." > > Per Gilles comment, Linux should not allow me to execute a > "set_irq_type" without holding a reservation to the IRQ. And, if I am > holding the reservation, then I could have configured the irq type via > the request_irq(). I am not so sure about that, from reading the code, it seems that set_irq_type should work even for an irq which you have not requested with request_irq. But the long term solution is to do something at RTDM level to handle this case. -- Gilles. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 13:18 ` Gilles Chanteperdrix @ 2010-08-10 19:01 ` Bob Feretich 2010-08-10 21:41 ` Gilles Chanteperdrix 0 siblings, 1 reply; 16+ messages in thread From: Bob Feretich @ 2010-08-10 19:01 UTC (permalink / raw) To: Gilles Chanteperdrix; +Cc: xenomai Comments inline.. On 8/10/2010 6:18 AM, Gilles Chanteperdrix wrote: > ...snipped... > The RTDM_IRQTYPE_EDGE is documented in RTDM API documentation: "Mark IRQ > as edge-triggered, relevant for correct handling of shared > edge-triggered IRQs. " Here: > http://www.xenomai.org/documentation/xenomai-2.5/html/api/group__rtdmirq.html The above quotation is the full extent of the documentation. The driver authors (we) ask the question, "Should I include this flag when I call rtdm_irq_request()?" The documentation leaves the answer ambiguous in the case where the RTDM_IRQTYPE_SHARED flag is not coded. It also creates confusion. We assume that RTDM_IRQTYPE_EDGE will cause hardware to be configured similar to request_irq().We knows that the specification of RTDM_IRQTYPE_EDGE is insufficient. Normally we need to specify which edge is to cause the interrupt. We question whether specifying RTDM_IRQTYPE_EDGE will cause our ISR to be entered on both rising and falling edges. The essence of this e-mail discussion eventually needs to be added to the rtdm_irq_request() documentation. Regards, Bob Feretich ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Xenomai-help] RTDM driver structure - an update 2010-08-10 19:01 ` Bob Feretich @ 2010-08-10 21:41 ` Gilles Chanteperdrix 0 siblings, 0 replies; 16+ messages in thread From: Gilles Chanteperdrix @ 2010-08-10 21:41 UTC (permalink / raw) To: Bob Feretich; +Cc: xenomai Bob Feretich wrote: > Comments inline.. > > On 8/10/2010 6:18 AM, Gilles Chanteperdrix wrote: >> ...snipped... >> The RTDM_IRQTYPE_EDGE is documented in RTDM API documentation: "Mark IRQ >> as edge-triggered, relevant for correct handling of shared >> edge-triggered IRQs. " Here: >> http://www.xenomai.org/documentation/xenomai-2.5/html/api/group__rtdmirq.html > The above quotation is the full extent of the documentation. The driver > authors (we) ask the question, "Should I include this flag when I call > rtdm_irq_request()?" The documentation leaves the answer ambiguous in > the case where the RTDM_IRQTYPE_SHARED flag is not coded. > > It also creates confusion. We assume that RTDM_IRQTYPE_EDGE will cause > hardware to be configured similar to request_irq().We knows that the > specification of RTDM_IRQTYPE_EDGE is insufficient. Normally we need to > specify which edge is to cause the interrupt. We question whether > specifying RTDM_IRQTYPE_EDGE will cause our ISR to be entered on both > rising and falling edges. Yes, the doc is not perfect, but in this case, I find the sentence unambiguous, this flag is only relevant for shared irqs. And Xenomai is free software, it means that: - in case of doubt you may have a look at the code; - we accept documentation patches. > > The essence of this e-mail discussion eventually needs to be added to > the rtdm_irq_request() documentation. I agree that we should try and improve the documentation. But in the rtdm_irq_request case, it is even the interface which we should improve by adding bits for setting the hardware, and when we are done, the documentation work will be much simpler. -- Gilles. ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2010-08-10 21:41 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-08-05 2:49 [Xenomai-help] RTDM driver structure Bob Feretich 2010-08-05 7:07 ` Gilles Chanteperdrix 2010-08-05 18:57 ` Bob Feretich 2010-08-05 19:27 ` Gilles Chanteperdrix 2010-08-07 2:22 ` [Xenomai-help] RTDM driver structure - an update Bob Feretich 2010-08-08 9:36 ` Everett Wang 2010-08-08 12:08 ` Gilles Chanteperdrix 2010-08-08 14:32 ` Everett Wang 2010-08-10 0:56 ` Bob Feretich 2010-08-10 7:43 ` Guenter Ebermann 2010-08-10 9:08 ` Bob Feretich 2010-08-10 13:33 ` Gilles Chanteperdrix 2010-08-10 13:41 ` Philippe Gerum 2010-08-10 13:18 ` Gilles Chanteperdrix 2010-08-10 19:01 ` Bob Feretich 2010-08-10 21:41 ` Gilles Chanteperdrix
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.