Periodic task in a Linux kernel module - linux

Currently I am developing GPIO kernel module for friendlyarm Linux 2.6.32.2 (mini2440). I am from electronics background and new to Linux.
The kernel module loaded at start-up and the related device file is located in /dev as gpiofreq.
At first time writing to device file, GPIO pin toggles continuously at 50kHz. At second time writing it stop toggling. At third time, it starts again, and so on.
I have wrote separate kernel module to generate freq. but CPU freezes after writing device file at first time. The terminal prompt is shown but I can not run any command afterwards.
Here is the code-snippet:
//calling function which generates continuous freq at gpio
static int send_freq(void *arg)
{
set_current_state(TASK_INTERRUPTIBLE);
for(;;)
{
gpio_set_value(192,1);
udelay(10);
gpio_set_value(192,0);
udelay(10);
}
return 0;
}
Here is the device write code,
which start or stop with any data written to device file.
if(toggle==0)
{
printk("Starting Freq.\n");
task=kthread_run(&send_freq,(void *)freq,"START");
toggle=1;
}
else
{
printk("Operation Terminated.\n");
i = kthread_stop(task);
toggle=0;
}

You are doing an infinite loop in a kernel thread, there is no room for anything else
to happen, except IRQ and maybe other kernel thread.
What you could do is either
program a timer on your hardware and do your pin toggling in an interrupt
replace udelay with usleep_range
I suggest doing thing progressively, and starting in the kHz range with usleep_range, and eventually moving to cust om timer + ISR
in either case, you will probably have a lot of jitter, and doing such gpio toggling may be a good idea on a DSP or a PIC, but is a waste of resources on ARM + Linux, unless you are hardware assisted with pwm capable gpio engine.

Related

What is the best way to sample periodicaly gpio-pins in Linux?

I like to sample a signal which is generated by the pins of my Raspberry Pi. I made the experience that high sample rates are difficult to realize.
First I done a fast approach with Python(super slow). Then I changed to ANSI C + the bcm2835.h lib. I gained significant performance gains.
Now I am asking my self the question: How to do the best sampling under Linux?
My tries were undertaken in user space. But what is about, switching to kernel space? I can write a simple character device kernel module. In this module the pins are periodically checked. If the state changed some information is put into a buffer. This i/o buffer is polled by a synchronous file read for a application in user space. The best solution for me would be, if the pin checking can be done with a fixed frequency(sample period should be constant for signal processing).
The set up for this could be:
#kernel: character module + kernel thread + gpio device tree interface + DSP at constant sampling time
#user space: i/o app reading synchronous from character module
Ideas/tips?
I have a solution for you.
I have written such a module:
https://github.com/Appyx/gpio-reflect
You can synchronously read any signal from the GPIO pins.
You can use the output and calculate the signal with your sampling rate.
Just divide the periods.

UART Interrupts disabling I/O on Sam3X8E/ Arduino Due

I am starting to use an Arduino Due for some project work which requires a UART and am confused by what looks like an interaction between UART interrupts and I/O.
My first piece of code was a small routine to set up the UART, send out data continuously by loading the transmit buffer upon receipt of a TXBE interrupt. I had the UART output hooked up to an oscilloscope and had set another I/O pin as a general purpose output which would flip state and therefore be used to trigger the scope when the transmit buffer was reloaded. Problem was that I was seeing UART data and it looked good, but the I/O wasn't flipping. At this point my loop() routine was empty so I set up another output port and in loop() just toggled its state as a sanity check. Still no output except for the UART.
Here's the code that I ended up with:
uint32_t tempo; // 32-bit temporary variable
boolean flag = true;
void UART_Handler(void) {
REG_UART_THR = 0x6DL; // load data into the transmit buffer
if (flag) {
REG_PIOD_SODR = 0x02L; // drive PD1 high
flag = false;
} else {
REG_PIOD_CODR = 0x02L; // drive PD1 low
flag = true;
}
}
void setup() {
// set up the UART I/O
REG_PIOA_IDR = 0x0300L; // disable interrupts on PA8 and PA9
tempo = REG_PIOA_ABSR; // get the current settings of the AB select register
REG_PIOA_ABSR = tempo & 0xFFFFFCFF; // set PA8 and PA9 to peripheral A control
REG_PIOA_PDR = 0x0300L; // disable parallel I/O for PA8 and PA9
NVIC_EnableIRQ(UART_IRQn); // enable UART interrupts in NVIC
// now set up the UART
tempo = REG_PMC_PCSR0; // get the current settings of the peripheral clock register 0
REG_PMC_PCER0 = tempo | 0x0100L; // enable the UART clocks
REG_UART_CR = 0x0CL; // reset UART receiver and transmitter
REG_UART_MR = 0x0800L; // set to normal outputs with no parity
REG_UART_BRGR = 0x89L; // baud rate set to 38400
REG_UART_IDR = 0x1FBL; // disable all UART interrupts
REG_UART_IER = 0x0800L; // enable TXBUFE interrupt
REG_UART_CR = 0x50L; // enable UART receiver and transmitter
// set up the debug outputs
REG_PIOD_IDR = 0x03L; // disable interrupts on PD0 and PD1
REG_PIOD_PER = 0x03L; // enable parallel I/O for PD0 & PD1
REG_PIOD_OER = 0x03L; // set PD0 & PD1 output enabled
REG_PIOD_CODR = 0x03L; // drive PD0 & PD1 low
}
void loop() // run over and over
{
REG_PIOD_SODR = 0x01L; // drive PD0 high
delay(1);
REG_PIOD_CODR = 0x01L; // drive PD0 low
delay(1);
}
the scope output can be viewed at http://www.iwanczuk.com/temp/scope1.png (don't have enough reputation here to post images!).
After staring at things for while and getting no insight I disabled the TXBUFE interrupts by commenting out the line REG_UART_IER = 0x0800L; // enable TXBUFE interrupt and the toggling of PortD1 was then visible but obviously no UART output (see http://www.iwanczuk.com/temp/scope2.png). It seems that the two are mutually exclusive which would be just silly if it were true. I am sure I'm missing something but I can't see or find what it is.
I have read the SAM3X8E data sheet to see if there's anything obvious I'm missing and if there is I can't see it. I've also done what I think are relevant web searches with no luck in finding a solution. I have also tried using general purpose outputs for the two outputs on port A and port D and have tried this on two Arduino Due boards with similar results on both.
Anyone have any ideas what I might be doing wrong? Thanks in advance.
Well, I have got to the bottom of this problem. Not sure it's the best answer but it's a solution. The long and short of it is to avoid TXBE interrupts. If I use TXEMPTY interrupts instead it works fine.
A line on page 168 of the Atmel data sheet says (sic) "A interrupt can enter pending state even it is disabled" so I wondered if the problem with TXBE was because I was not clearing the pending interrupt before or even inside the ISR so I added NVIC_ClearPendingIRQ(UART_IRQn); at the start of the ISR and also just before I enabled the TXBE interrupt but the (mis)behaviour didn't change.
The operation of TXEMPTY is still a little odd (to me) because it appears that the interrupt is generated by the transmit shift register just being empty, not when it goes empty. If you enable interrupts without having loaded the transmit buffer you will immediately get an interrupt. Some may like this "self=priming' behaviour, but it doesn't do it for me. I am writing my sending routine such that the TXEMPTY interrupt is not enabled until the transmitter has been loaded with the first byte to be sent.
Based on this post on the Arduino Forum: http://forum.arduino.cc/index.php?topic=186388.0 I presume that the USARTs have a similar issue.
Hopefully this will help others.
I just realised what could be the real error at the source of my problem. The UART interrupt register descriptions talk about the TXBUFE bit in the context of transmit buffer empty and so my assumption was that this is the bit that tells me when I can put another byte into the transmit holding register. However the UART Status Register description say that the TXBUFE bit is "the buffer full signal from the transmitter PDC channel". The latter puts a whole different slant on what this bit does. According to the UART Status Register description the bit I need to be looking at is the TXRDY bit!

Last Reboot detection on PhyCORE-AM335x-PD13.1.2 Linux 3.2

In an embedded system using BSP linux 3.2 on the sitara AM3359, at application startup, I want to detect what caused the last reboot and save this status in one of two counters: a Watchdog reset and a Power-on reset.
Usually in a MCU, I test the watchdog by reserving spot in the ram and write special key on the first boot and reset using the watchdog. If not there when reboot it's power on if it's there it's a watchdog reset.
My first question is, how to save the key variables on RAM that would survive a reboot or a watchdog reset ?
It's seem something clean the ram at boot...can I disable that?
There usually a register with that information. On AM335x there is the PRM_RSTST register with the bit (WDT1_RST), I am using ioctl() with WDIOC_GETBOOTSTATUS to Check if the last boot is caused by watchdog or it's power-on-reset. This call doesn't return me something I can understand. Can somebody explain it ? How can I get this register...
Power ON:
test1: 1076092848
test2: 1076113328
test3: 1075589040
test4: 1076203440
watchdog:
test5: 1076481968
test6: 1075732400
test7: 1075965872
code use:
/* Check if last boot is caused by watchdog */
if (ioctl(fd, WDIOC_GETBOOTSTATUS, &bootstatus) == 0) {
fprintf(stdout, "Last boot is caused by : %s, bootstatus= %d\n",
(bootstatus != 0) ? "Watchdog" : "Power-On-Reset", bootstatus);
} else {
fprintf(stderr, "Error: Cannot read watchdog status\n");
exit(EXIT_FAILURE);
}
Is there another way to get this information (mmap, write driver, sys, etc)?
I would propose you to use your bootloader to see processor register values (for u-boot I beleive the command is reginfo). The same way (but another command) for the memory where you stock watchdog keys. Once debugged with your bootloader you can think about passing them to the kernel.
I start by using terminal command devmem 0x44E00F08 (busybox) to see if reading the physical memory will work then I use mmap() to read the PRM_RSTST register and know if the last reset was watchdog reset.

Interrupt handling (Linux/General)

On the mainbord we have an interrupt controller (IRC) which acts as a multiplexer between the devices which can raise an interrupt and the CPU:
|--------|
|-----------| | |
-(0)------| IRC _____|______| CPU |
-(...)----| ____/ | | |
-(15)-----|/ | |--------|
|-----------|
Every device is associated with an IRQ (the number on the left). After every execution the CPU senses the interrupt-request line. If a signal is detected a state save will be performed and the CPU loads an Interrupt Handler Routine which can be found in the Interrupt Vector which is located on a fixed address in memory. As far as I can see the Number of the IRQ and the Vector number in the Interrupt Vector are not the same because I have for example my network card registered to IRQ 8. On an Intel Pentium processor this would point to a routine which is used to signal one error condition so there must be a mapping somewhere which points to the correct handler.
Questions:
1) If I write an device driver and register an IRQ X for it. From where does the system know which device should be handled? I can for example use request_irq() with IRQ number 10 but how does the system know that the handler should be used for the mouse or keyboard or for whatever i write the driver?
2) How is the Interrupt Vector looking then? I mean if I use the IRQ 10 for my device this would overwrite an standard handler which is for error handling in the table (the first usable one is 32 according to Silberschatz (Operating System Concepts)).
3) Who initialy sets the IRQs? The Bios? The OS?
4) Who is responsible for the matching of the IRQ and the offset in the Interrupt Vector?
5) It is possible to share IRQS. How is that possible? There are hardware lanes on the Mainboard which connect devices to the Interrupt Controller. How can to lanes be configured to the same Interrupt? There must be a table which says lane 2 and 3 handle IRQ15 e.g. Where does this table reside and how is it called?
Answers with respect to linux kernel. Should work for most other OS's also.
1) If I write an device driver and register an IRQ X for it. From where does the system know which device should be handled? I can for example use request_irq() with IRQ number 10 but how does the system know that the handler should be used for the mouse or keyboard or for whatever i write the driver?
There is no 1 answer to it. For example if this is a custom embedded system, the hardware designer will tell the driver writer "I am going to route device x to irq y". For more flexibility, for example for a network card which generally uses PCI protocol. There are hardware/firmware level arbitration to assign an irq number to a new device when it is detected. This will then be written to one of the PCI configuration register. The driver first reads this device register and then registers its interrupt handler for that particular irq. There will be similar mechanisms for other protocols.
What you can do is look up calls to request_irq in kernel code and how the driver obtained the irq value. It will be different for each kind of driver.
The answer to this question is thus, the system doesn't know. The hardware designer or the hardware protocols provide this information to driver writer. And then the driver writer registers the handler for that particular irq, telling the system what to do in case you see that irq.
2) How is the Interrupt Vector looking then? I mean if I use the IRQ 10 for my device this would overwrite an standard handler which is for error handling in the table (the first usable one is 32 according to Silberschatz (Operating System Concepts)).
Good question. There are two parts to it.
a) When you request_irq (irq,handler). The system really doesn't program entry 0 in the IVT or IDT. But entry N + irq. Where N is the number of error handlers or general purpose exceptions supported on that CPU. Details vary from system to system.
b) What happens if you erroneously request an irq which is used by another driver. You get an error and IDT is not programmed with your handler.
Note: IDT is interrupt descriptor table.
3) Who initialy sets the IRQs? The Bios? The OS?
Bios first and then OS. But there are certain OS's for example, MS-DOS which doesn't reprogram the IVT set up by BIOS. More sophisticated modern OS's like Windows or Linux do not want to rely on particular bios functions, and they re-program the IDT. But bios has to do it initially only then OS comes into picture.
4) Who is responsible for the matching of the IRQ and the offset in the Interrupt Vector?
I am really not clear what you mean. The flow is like this. First your device is assigned an irq number, and then you register an handler for it with that irq number. If you use wrong irq number, and then enable interrupt on your device, system will crash. Because the handler is registered fro wrong irq number.
5) It is possible to share IRQS. How is that possible? There are hardware lanes on the Mainboard which connect devices to the Interrupt Controller. How can to lanes be configured to the same Interrupt? There must be a table which says lane 2 and 3 handle IRQ15 e.g. Where does this table reside and how is it called?
This is a very good question. Extra table is not how it is solved in kernel. Rather for each shared irq, the handlers are kept in a linked list of function pointers. Kernel loops through all the handlers and invokes them one after another until one of the handler claims the interrupt as its own.
The code looks like this:
driver1:
d1_int_handler:
if (device_interrupted()) <------------- This reads the hardware
{
do_interrupt_handling();
return MY_INTERRUPT;
}else {
return NOT_MY_INTERRUPT;
}
driver2:
Similar to driver 1
kernel:
do_irq(irq n)
{
if (shared_irq(n))
{
irq_chain = get_chain(n);
while(irq_chain)
{
if ((ret = irq_chain->handler()) == MY_INTERRUPT)
break;
irq_chain = irq_chain->next;
}
if (ret != MY_INTERRUPT)
error "None of the drivers accepted the interrupt";
}
}

Linux device driver handling multiple interrupt sources/vectors

I am writing a device driver to handle interrupts for a PCIe card, which currently works for any interrupt vector raised on the IRQ line.
But it has a few types that can be raised, flagged by the Vector register. So now I need to read the vector information and be a bit cleverer...
So, do I :-
1/ Have separate dev nodes /dev/int1, /dev/int2, etc for each interrupt type, and just doc that int1 is for vector type A etc?
1.1/ As each file/char-devices will have its own minor number, when opened I'll know which is which. i think.
1.2/ ldd3 seems to demo this method.
2/ Have one node /dev/int (as I do now) and have multiple processes hanging off the same read method? sounds better?!
2.1/ Then only wake the correct process up...?
2.2/ Do I use separate wait_queue_head_t wait_queues? Or different flag/test conditions?
In the read method:-
wait_event_interruptible(wait_queue, flag);
In the handler not real code! :-
int vector = read_vector();
if vector = A then
wake_up_interruptible(wait_queue, flag)
return IRQ_HANDLED;
else
return IRQ_NONE/IRQ_RETVAL?
EDIT: notes from peoples comments :-
1) my user-space code mmap's all of the PCIe firmware registers
2) User-space code has a few threads, each perform a blocking read on the device driver device nodes, which then returns data from the firmware when an interrupt occurs. I need the correct thread woken up depending on the interrupt type.
I am not sure I understand correctly what you mean with the Vector register (a pointer to some documentation would help me precise for your case).
Anyway, any PCI device gets a unique interrupt number (given by the BIOS or some firmware on other architectures than x86). You just need to register this interrupt in your driver.
priv->name = DRV_NAME;
err = request_irq(pdev->irq, your_irqhandler, IRQF_SHARED, priv->name,
pdev);
if (err) {
dev_err(&pdev->dev, "cannot request IRQ\n");
goto err_out_unmap;
}
One other thing that I do not really understand is why you would export your interrupts as a dev node: interrupts are certainly something that need to remain in your driver/kernel code. But I guess here you want to export a device that is then accessed in userspace. I just find /dev/int no to be a good naming.
For your question about multiple dev nodes: if your different interrupt sources then provide access to different hardware resources (even if on the same PCI board) I would go for option 1), with a wait_queue for each device. Otherwise, I would go for option 2)
Since your interrupts are coming from the same physical device, if you chose option 1) or option 2), the interrupt line will have to be shared and you will have to read the vector in your interrupt handler to define which hardware resource raised the interrupt.
For option 1), it would be something like this:
static irqreturn_t pex_irqhandler(int irq, void *dev) {
struct pci_dev *pdev = dev;
int result;
result = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &myirq);
if (result) {
int vector = read_vector();
if (vector == A) {
set_flagA(flag);
} else if (vector == B) {
set_flagB(flag);
}
wake_up_interruptible(wait_queue, flag);
return IRQ_HANDLED;
} else {
return IRQ_NONE;
}
For option 2, it would be similar, but you would have only one if clause (for the respective vector value) in every different interrupt handler that you would request for every node.
If you have different chanel you can read() from, then you should definitely use different minor number. Imagine you have a card whith four serial port, you would definitely want four /dev/ttySx.
But does your device fit whith this model ?
First, I assume you're not trying to get your code into the mainline kernel. If you are, expect a vigorous discussion about the best way to do this. If you're writing a simple interrupt handling driver for a card which is mostly driven by mmap from user-space, there are a lot of ways to solve this problem.
If you use multiple device nodes (option 1), you can also implement poll so that a single application can open multiple device nodes and wait for a selection of interrupts. The minor number will be sufficient to tell them apart. If you have a wake queue for each vector, you can wake only the relevant listeners. You'll need to latch the vector after a successful poll to be sure that the read succeeds.
If you use a single device node (option 2), you'll need to add some extra magic so that the threads can register their interest in particular interrupt vectors. You could do this with an ioctl, or have the threads write the interrupt vectors to the device. Each thread should open the device node to get its own file descriptor. You can then associate the list of requested vectors with each open file descriptor. As a bonus, you can let the application read the interrupt vector from the device, so it knows which one happened.
You'll need to think about how the interrupt gets cleared. The interrupt handler will need to remove the interrupt, then store the result so it can be passed to user-space. You might find a kfifo useful for this rather than a wait queue. If you have a fifo for each open file descriptor, you can distribute the interrupt notifications to each listening application.

Resources