On Fri, 13 Jul 2007, Kevin Cozens wrote:
> Greetings, all.
>
> I have a kernel device driver for a TS-7250 which is generating timer-based
> interrupts every 500uS. The interrupt handler just flips some bits on port B
> resulting in the generation of 1kHz signals on port B. The problem I have is
> that my user space application also needs to control some of the bits of port
> B (but not the ones the kernel driver is changing).
>
> The simple solution would be to have my application disable all interrupts
> during the read/modify/write of port B. The application doesn't need to modify
> the bits of port B that often and the read/modify/write would only take a few
> instructions so they would only be off for a very short time.
This solution only has the illusion of being simple - at the very least,
it would cause jitter in your output from where interrupts are disabled
when the timer fires, and at worst you could mess up a whole host of
kernel timing and other services.
If you want to do atomic operations, do them in kernel space which is
designed to support them.
> Can I issue disable/enable interrupts instruction in user space (via asm
> directives?) or will I be forced to implement ioctl support in my device
> driver to control the other bits of port B?
I'd add a character device to /dev or /proc which accepts bytes, stores
them in your kernel module somewhere and mask+ors them to the output every
interrupt. Avoids anything complex in userspace, allows all the bit
masking and whatnot to happen in one place, but also puts a <=500uS delay
on output from userspace apps.
If the delay is unacceptable, you could add another port write to the
dev_read function that accepts bytes written to the device node, again
keeping masking and whatnot in the one file as well as allowing high speed
streams of data from userspace to be accurately represented without
disturbing the timer.
Here's some c-like pseudocode in case I'm not clear:-
(note that I've never actually written a kernel module before, so this may
not be how it actually works)
--kernel module--
// bitmask for timer, userspace can have all the 0 bits
#define timer_mask 0b00000100
// current port state
static byte portdata
module_init()
portdata = 0;
create(/dev/portB, DEV_CHAR, &userspace_wrote_to_dev_node,
&userspace_read_dev_node);
setup_timer_intr();
userspace_wrote_to_dev_node(char *data, int len)
for (i=0;i<len;i++)
// (timer bits) | (new userspace bits)
out(portB, portdata = (portdata & timer_mask) | (data[i] &
~timer_mask));
// return the port's current output state
userspace_read_dev_node(char *buf, int buflen)
#if CONFIG_INCLUDE_TIMER_BITS
buf[0] = portdata;
#else
buf[0] = portdata & ~timer_mask;
#endif
return 1; // number of bytes written to buffer
timer_intr()
// (userspace bits) | (new timer bits)
out(portB, portdata = (portdata & ~timer_mask) | ((~portdata) &
timer_mask));
--end--
--userspace--
int port;
main()
if ((port = open(/dev/portB)) < 0)
perror("can't open /dev/portB");
write(port, "someData");
while(do_some_calculations(&more_data))
write(port, more_data);
--end--
If it's possible for the kernel to preempt the dev_write call, or you want
to use this on a multi-processor system, protect portdata with a mutex or
spinlock or something.
By chance, I currently have a very relevant article open (watch out for
long line splitting mail clients & servers) -
http://www.linuxdevcenter.com/pub/a/linux/2007/07/05/devhelloworld-a-simple-introduction-to-device-drivers-under-linux.html
In theory, you could grow such a system into a generic port driver which
can allocate different bits to different drivers/processes in either
kernel or userspace and a generic timer driver which would be incredibly
useful to many people on this mailing list. Simply posting the code you
have now could easily allow someone else to do it for us :)
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/ts-7000/join
(Yahoo! ID required)
<*> To change settings via email:
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|