Driver Development Kit (DDK)

cancel
Showing results for 
Search instead for 
Did you mean: 

register guide for 6220, 6224

Solved!
Go to solution

Hi Kevin-

Yes, the address should always be 32-bit but the register widths may vary, as described in the M Series Register Map document.  The method you described should work (assuming NI_Write() is correctly implemented to write to offsets from BAR1).

If you must write your own methods for accessing registers (instead of using the MHDDK chipobject libraries), you should also make sure to initialize the MITE properly as shown in main.cpp under initMite().  Until you complete this step, the BAR1 registers will not be accessible.

Tom W
National Instruments
0 Kudos
Message 11 of 29
(11,587 Views)

Thanks Tom.

Good explain and clear guide

BR Kevin

0 Kudos
Message 12 of 29
(11,579 Views)

Hello Tom

I know that NI622X PCI device(s) are consist of 3 port as Port 0,1,2

Normally to use Port0 , user have to set  "board->DIO_Direction.writeRegister (0xFF)" then read/write is activaed.
And to use Port1,2 , user have to set  "IO_Bidirection_Pin" and  "PFI_Output_Select_1~6" then read/write is activated.      

Q[1] Can use(access to rea/write) Port0 and Port1,2 simultaneously ?

Q[2] Can it be possible combination Port0+Port1,2+AnalogInput simultaneously ?

Q[3] Refer to Dioex1.cpp, you set as "board->DIO_Direction.writeRegister (0xFF)" before start read/Write.

I'm interesting the value "0xFF", what the meaning of 0xFF ?

At the case of NI6224, it has 32 I/O at Port0 while NI6220 has 8 I/O.

Do I have to set 0xFFFF for NI6224 --> 32 I/O at port0 ?

 

Q[4] Refer to your RTX sample code (osiUserCode.cpp), it manage two baseaddress.

   deviceBar0.QuadPart = pciDeviceData->u.type0.BaseAddresses[0];
   deviceBar1.QuadPart = pciDeviceData->u.type0.BaseAddresses[1];

   And save it as follow for after usage by "RtMapMemory".

   bus->_physBar[0] = deviceBar0.LowPart;
   bus->_physBar[1] = deviceBar1.LowPart;

Here I attach my code: If I can succeeded to access second address, everything is clear.

Currently it works well : read eeprom information with successfully

But fail to access second address.

I can't find any issue in my code..

Hope to listen your smart opinion.

BR Kevin

 

0 Kudos
Message 13 of 29
(11,553 Views)
Hi Kevin-
 
Q[1] Can use(access to rea/write) Port0 and Port1,2 simultaneously ?
 
No.  You must use the methods shown in the examples to access Port0 and Ports1/2.  There is no way to synchronize Port0 with Port1/2.
 
Q[2] Can it be possible combination Port0+Port1,2+AnalogInput simultaneously ?
 
No.  There is no way to synchonize digital and analog operations using the MHDDK.
 
Q[3] Refer to Dioex1.cpp, you set as "board->DIO_Direction.writeRegister (0xFF)" before start read/Write.
 
DIO_Direction is a 32-bit register where each bit refers to the corresponding line in Port0.  A '1' indicates a line will be used for digital output and a '0' indicates digital input.  So, to set all 32 lines to output you would need to write 0xFFFFFFFF to the register.
 
Q[4] Refer to your RTX sample code (osiUserCode.cpp), it manage two baseaddress. [...]  And save it as follow for after usage by "RtMapMemory".
 
Actually, the physical address (rather than mapped virtual address) is used by the initMite() function in the MHDDK example.  It looks like your example is using the virtual address.  I suspect that something is going wrong with the mapping.  Can you try using the physical address?  Does the device work when you use the MHDDK sample code?  How are you verifying that the BAR1 registers are unavailable?
Tom W
National Instruments
0 Kudos
Message 14 of 29
(11,540 Views)
Hello Tom
thanks for your explain.
 
Q[4] I succeeded read eeprom information such as serial number via "readFromEeprom" which requred both Bar0 and Bar1 address.
If my two mapping address (Bar0, Bar1) were wrong, it will fail to read serial number from eeprom.
So in my guess two memory mapping may wright.
If I change Bar1 as physical address, RTX return exception error.
 
The way how to verify Bar1 is simple.
 
void Start_DIO(UCHAR order)
{
 ULONG   addr = message->AnyPci[order].vMapMem1;
 Rtx_pci_poked(addr + 0x28/*DIO_Direction*/, 0xFF);
}
 
ULONG Port0_Read(UCHAR order)
{
 ULONG   addr = message->AnyPci[order].vMapMem1;

 return Rtx_pci_peekd(addr + 0x24/*Static_Digital_Input*/);
}
 
ULONG Port0_Write(ULONG data, UCHAR order)
{
 ULONG   addr = message->AnyPci[order].vMapMem1;
 return Rtx_pci_poked(addr + 0x24/*Static_Digital_Output*/, data);
}
 
Srart_DIO-->A=Port0_Read-->Port0_Write-->B=Port0_Read
 then compare A and B just like before and after.
 
But in this way always return no difference. So I'm confused...
Do I have to add additional register offset ?
Could you tell me proper register which make as standard to find address offset?
It must be contain reserved value..
 
BR Kevin
 
0 Kudos
Message 15 of 29
(11,537 Views)

Hello Tom

Forget my previous message,... I solve it. You are right

 

Back to [Q1] and Q[2] :  refer to your remark, I have to manage port0, and port1,2 respect. right?

Analog Input also ..?

 

many many thanks

BR Kevin

0 Kudos
Message 16 of 29
(11,532 Views)

Hi Kevin-

I do not understand your question.  You must control port0 by itself, port1/2 by itself, and analog input by itself in the MHDDK.  There is no way to control any combination of the three by using a single call, and there are no examples to synchronize the three.  Is this what you are asking?

Tom W
National Instruments
0 Kudos
Message 17 of 29
(11,526 Views)
Hi Tom
 
There are misunderstanding btw us.
I know that each of Port0, Port1/2 and AI requires dedicated register setting (initialization).
My question was NOT asking single call.
 
Due to NI sample code are depicted each case as respective.
But my driver and application will process at same time Port0/1/2/AI.
 
So I want to avoid recursive initialize of these three area whenever API call. Is it make sence ?
 
Boot up system then move to INITIALIZE all NI device resource
 1] initialize Port0
 2] initialize Port1/2
 3] initialize AI
 
Then my driver will wait event of message which came from application.
 4] DIO can be done throughout Port0, 1/2 at any time without [1], [2]
 5] AI can be done through AI at any time without [3]
 
Is it make sence  or stupid scheme?
 
If it is not permitted, I have no way but set each register, whenever application call.
 
BR Kevin
 
0 Kudos
Message 18 of 29
(11,520 Views)

Hello Tom

My project moves final stage to integrate it with test app.

 

[Q#1] aiConfigureChannel -- aiGetScalingCoefficients

Refer to Aiex1.cpp, user can select gain value by call "aiConfigureChannel".

// intervalIdx
//    0 -> +/- 10V
//    1 -> +/- 5V
//    2 -> +/- 2V
//    3 -> +/- 1V
//    4 -> +/- 500mV
//    5 -> +/- 200mV
//    6 -> +/- 100mV

---------------------------------------------------------------------------------------

aiConfigureChannel (board,
                            i,  // channel number
                            1,  // gain -- check ai.h for allowed values

But at the end of Aiex1.cpp "aiGetScalingCoefficients " also needs same kind of value

(at secondparameter), but different value from above.

aiGetScalingCoefficients (eepromMemory, 0, 0, 0, &scale);

In my guess , above two values must be same as parallel,..isn't it?

 

[#2] differential / single

AI can be controlled by two way as differential & single.

All sample code (aiex1, aiex2.cpp) adapted differental as default by call "aiConfigureChannel " with follow macros.

kAI_Config_PolarityBipolar / kAI_Config_Channel_TypeDifferential

if user want to change it as single instead of differential, which macro(s) are proper combinations & is there any modify area except aiConfigureChannel ?

 

BR Kevin

0 Kudos
Message 19 of 29
(11,413 Views)

Hi Kevin-

You are correct- there is an error in the example code where channel range and scaling coefficient intervalIdx are concerned.  You should make sure that the value in aiConfigureChannel() from ai.h for intervalIdx match the value for aiGetScalingCoefficients() from scale.h.  Note that the two values may not be the same number.

The values for the channelType parameter of aiConfigureChannel() are declared as an enum of type tMSeries::tAI_Config_FIFO_Data::tAI_Config_Channel_Type in tMSeries.h:

typedef

enum {
kAI_Config_Channel_TypeCalibration = 0,
kAI_Config_Channel_TypeDifferential = 1,
kAI_Config_Channel_TypeNRSE = 2,
kAI_Config_Channel_TypeRSE = 3,
kAI_Config_Channel_TypeAux = 5,
kAI_Config_Channel_TypeGhost = 7,
} tAI_Config_Channel_Type;

Tom W
National Instruments
0 Kudos
Message 20 of 29
(11,407 Views)