From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

X Series 6321 & 6323: Setting Up Interrupts

Solved!
Go to solution

Hi,

 

I'm in contact with the NI support people now, and they suggested to open an extra thread on the interrupt topic to make it more prominent in the forum.

 

And here's what it's all about:

 

I've written a Linux/Xenomai driver for the X 6321 / 6321 using programmed I/O. It works fine, but we're too slow in our system context.

 

So my next idea was to use DMA. This also works, but only for a maximum of 4 analog input channels. Using more brings the whole system to a grinding halt.

 

So I thought I use interrupts to catch the input at the end of the DMA-transfer. Following the stanza in the reference manual I set CPU_Int and STC3_Int to 1.

 

I also set:

- Channel_Total_Transfer_Count_Compare_Register_LSW = 1, so I'd get an interrupt as soon as the first byte arrives - certainly a reason to celebrate.

- Notify_On_Total_Count = 1

- Arm_Total_Count_Int = 1

- Gen_Interrupt_Enable = 1

- ... and a few others, to provoke some reaction

 

What I see from the printk-s in my driver is that the status registers Vol_CPU, and Vol_DMA go up and down as I would expect them to.

 

On the Linux/Xenomai side everything looks okay: The device registers on IRQ 17, as confirmed by pci_enable_device, and also /proc/irq.

 

But I can't catch any interrupts on the bus, i.e. my interrupt handler is never called...

 

Any ideas?

 

Best regards,

 

Philip Hiller

0 Kudos
Message 1 of 12
(12,092 Views)

Another small observation:

 

As I said, the driver works fine with 4 channels, but not with 5. Furthermore the Vol_DMA doesn't switch to 1, when the DMA transfer is/should be finished.

 

This also makes me wonder, why the examples in the DDK use a maximum of 4 AI channels.

0 Kudos
Message 2 of 12
(12,088 Views)

Hello philler,

 

Is there any new status on this problem?

 

From looking at the DAQ-STC3 manual, I would expect that the following register accesses would be necessary to get an interrupt from DMA.

 

1. CHInCH Interrupt_Status_Register Set_CPU_Int = 1

2. DMA Control Registers Channel_Control_Register Notify_On_Total_Count or Notify_On_Done = 1

3. DMA Control Registers Channel_Operation_Register Arm_Total_Count_Int = 1 (if you want Notify_On_Total_Count)

4. Remember to generate the DMA Stop in order to get the Notify_On_Done interrupt.

 

When your ISR gets called verify the following.

 

1. Check the CHInCh Volatile_Interrupt_Status_Register Vol_Int and Vol_DMA...both should be set.

2. DMA Control Registers Channel_Volatile_Status_Register should have Vol_Int, Vol_Total_Count or Vol_Done set

 

To verify how you are accessing the board could you provide more information about the following:

1. What example are you building on in the X Series DDK? I would expect that a DMA example could be modified to start using interrupts.

2. Can you provide a full list of registers accessed and the register contents while you are enabling DMA?

 

Thanks,

Steven T.

 

 

0 Kudos
Message 3 of 12
(12,037 Views)

Hi Steven T.,

 

I just got back to working on this problem.

 

Here's a little more explanation on our system context: The frequency of our system is 10 kHz, i.e we have 100 µs for a measurement cycle and reacting to these values with control signals. There are several more cards in the system, so time is a very limted resource.

 

In developing the driver for the 6321/6323 cards we first used register level programming. This works well for one 6321 card in the system with 8 differentially connected analog input channels. Adding a second 6321 card braks the timing boundaries. We can work around this problem by slowing down our internal frequency to 2 kHz; but that's not what we had in mind.

 

So we tried using DMA (along the lines of aiex1.cpp). This proved to be no faster than the RLP solution. The next idea was to add interrupts:

 

1.) Catch the 10 kHz from our system board.

2.) Trigger the DMA transfer.

3.) Catch the Total_Count interrupt from the 6321 card.

4.) Transfer the card data from the DMA buffers to further processing.

 

And 3.) is where we are stuck. The ISR isn't being called. Here's what I do to hopefully get the interrupt configured:

 

AIStreamCircuit.StreamTransferLimitReg.writeStreamMinPayloadSize(0, &Status);

AIStreamCircuit.StreamTransferLimitReg.writeStreamMaxPayloadSize(DmaAiSizeInBytes, &Status);

CHInCh.Interrupt_Mask_Register.setSet_CPU_Int(1, &Status);

Channel_Total_Transfer_Count_Compare_Register_LSW.writeRegister(DmaAiSizeInBytes, &Status);

Channel_Total_Transfer_Count_Compare_Register_MSW.writeRegister(0, &Status);

Channel_Control_Register.setNotify_On_Total_Count(1, &Status);

Channel_Operation_Register.setArm_Total_Count_Int(1, &Status);

 

Actually I can see the Volatile_Interrupt_Status_Register and Channel_Volatile_Status_Registers going up and down as I would expect, but still the ISR isn't called 😞

 

As for your further questions:

 

1.) I'm using aiex3.cpp. There isn't an example that shows how to use interrupts.

 

2.) Enabling and using DMA works fine. It's the interrupts that are causing the trouble. Can you send me a code snippet of what you want to see?

 

Regards,

 

Philip

 

 

 

0 Kudos
Message 4 of 12
(12,017 Views)

To get a full list of register accesses, you can modify all of the chip objects' read/write methods. Capture the name of the chip object, the offset of the register, and the data that is read from or written to the register.

 

If all of the chip objects are modified in this way, you should have a complete, ordered list of registers getting accessed to set up your device.

 

I can then take this list and compare it with the manual to make sure the expected results will happen.

 

Thanks,

Steven T.

0 Kudos
Message 5 of 12
(12,006 Views)

Hi Steven,

 

I've put debug outputs in the read/write methods, see the attachement. As I said, the driver works with RLP and, alternatively, DMA, but the interrupts won't work. The list stops after configuring the interrupts, because the the printk-buffer gets overrun.

 

I'll take a look at the code Bertrand (bcachet) sent and also have a look in the Xenomai IPIPE/ADEOS corner - perhaps something is going wrong there.

 

I'm looking forward to your feedback.

 

Regards,

 

Philip

0 Kudos
Message 6 of 12
(11,996 Views)

Hi Steven,

 

is there anything new on this topic?

 

Regards,

 

Philip

0 Kudos
Message 7 of 12
(11,982 Views)
Solution
Accepted by topic author philler

Hello,

 

I do have some more information about what I've found.  First, I see that your prints largely follow the aiex3.cpp example, which uses DMA.  I've noticed a few things about the prints.

 

1. I don't see anywhere that the DMA is actually starting. The last access to the Channel_Operation_Register (AI Offset is 0x2058), has Arm_Total_Count_Int, CLR_TTC, STOP.  Bit 0 is never set. Another issue I see is that Arm_Total_Count_Int should not be set on the same access that also sets START or STOP. See the X Series Driver Development Kit Reference Manual for more details.

2. When enabling interrupts on the CHInCh, both Set_CPU_Int and Clear_CPU_Int are set during the same access. Same with Set_STC3_Int and Clear_STC3_Int.

3. I also don't see anything regarding getting the acquisition to start (is the acquisition using a hardware trigger?).

4. Either the ISR is never called or its prints are missing.

 

I hope this helps 🙂

Steven T.

0 Kudos
Message 8 of 12
(11,975 Views)

Hi Steven,

 

this certainly sheds some new light on the problem.

 

I've reprogrammed the system during the past few days so that it can run at almost any frequency. I'll slow it down to 100 Hz or below tomorrow and see what happens. At 100 Hz the printks should work without crashing the machine.

 

I'll be in touch & thanks,

 

Philip

0 Kudos
Message 9 of 12
(11,971 Views)

Hi Steven,

 

thank you for pointing me in the right direction in your last mail. My interrupt service routine  is now receiving interrupts from the card!

 

But there aren't any data in the DMA buffer.

 

Basically I do a dma->start() followed immediately by a dma->stop() in the system ISR. The dma-stop()  asserts an interrupt on the bus as soon as the DMA transfer is finished, and my ISR gets called.

 

I want my ISR to simply read the data from the buffer and push it up to higher levels. This is a dma->read(). But it's not returning any data.

 

Do you have any thoughts on this?

 

Theres a register level read write trace attached. Look for CopyAiDmaBufferToRegisterMap, my ISR.

 

Best regards,

 

Philip

 

0 Kudos
Message 10 of 12
(11,951 Views)