workingmailing@163.com wrote:
FW is doing:
Bulk out data to device, device received the 16KB, generate the interrupt, in the ISR, it prepare 16KB for ISO in, response the Host ACK IN.
App is doing:
Write 16KB –> delay(time) –> Read(16KB).
…
2. Even I think 2ms is enough for device to prepare 16KB for ISO in, but it happened the first DP is 0 length packet, and the after 15 DP is 1KB in the 16KB read.
So I change the delay to 5ms, it also happen the same case.
…
SO in this case, I think maybe device prepare the buffer/data for ISO in take more than 2ms/5ms sometimes.
But why it take so long, as each 1KB only take 15us.
It might only takes 15us inside your device, but remember that your iso
pipe is gated not only by the max packet size, but by the interval. For
example, if you have a full speed device, and you specify a max packet
size of 512 bytes and an interval of 1, it is going to take 32ms to
transfer 16k bytes.
Based on your description, it sounds like you shouldn’t be using an
isochronous pipe at all.
What’s the processor in your device? Most of the microprocessors in the
generic USB chips can’t possibly prepare 1kB of data in 15us. In the
Cypress FX2, for example, the processor runs about 4 MIPs.
- Second,
After check the struct:
typedef union _ LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
};
LONGLONG QuadPart;
} LARGE_INTEGER;
it is a union,
- in what case, we use it as struct , and in what case, we use it as LONGLONG?
A union just provides multiple ways to access the same piece of memory.
When NT was developed, the Microsoft compilers did not have a
fundamental 64-bit data type. So, you had to use HighPart and LowPart
to access the upper and lower halves. Today, the compiler has a
built-in __int64 type (which is what LONGLONG is), so it’s usually more
convenient to use QuadPart.
- does LARGE_INTEGER have relationship with OS system, and hardware such CPU, and PCIe?
I don’t know what that means. A LARGE_INTEGER is just a 64-bit
integer. If the Microsoft compilers had had __int64 in 1989, the
LARGE_INTEGER structure would not exist.
- QuadPart is a 64 bit variable, it is print with %I64d,
but some code example type change it as:
double dqFreq=(double)nFreq.QuadPart;
Here is my print result:
Freq-QuadPart:
2435898(d), 10462102246391808(I64d), 0.000000(f)
dqFreq:
0(d), 1094882717(I64d), 0.000000(f)
why they have different in %I64d and %d, and why it is 0 in %f mode?
Because neither of those are actually printing what you THINK they are
printing. Remember that the printf function does not really know the
types of the variables you are sending. It just gets bytes on the
stack. It has to TRUST that you are telling the truth. In this case
you are lying.
I assume your statement was:
printf( “%d(d) %I64d(I64d) %f(f)\n”, nFreq.QuadPart, nFreq.QuadPart,
nFreq.QuadPart );
When you pass nFreq.QuadPart, it gets pushed on the stack as a 64-bit
quantity. So, when printf is called, the stack looks like this:
esp –> return address
esp+4 –> pointer to format string
esp+8 –> nFreq.LowPart
esp+12 –> nFreq.HighPart
esp+16 –> nFreq.LowPart
esp+20 –> nFreq.HighPart
esp+24 –> nFreq.LowPart
esp+28 –> nFreq.HighPart
Now, the first thing in your format string is %d. printf assumes that
you gave it a 32-bit quantity, so it pulls one dword from the stack (in
this case, it gets the LowPart). Next, there is a %I64d. printf
assumes that you gave it a 64-bit quantity, so it pulls two dwords from
the stack. But since you lied about the first parameter, it’s going to
get the two halves in the wrong order. When it sees the %f, it assumes
you gave it a double-precision floating point value. But, what you gave
it was a 64-bit integer, and in this case the two halves are swapped
because you lied on the first parameter.
The same thing happens in your second example. Floating point values
are pushed on the stack as 64-bit quantities, but again you have TOLD it
that your first thing is a 32-bit integer. After that, the rest of the
items are screwed up because the stack is messed up.
You cannot print a floating point value with %d, nor print an integer
value with %f. printf cannot do any conversions, because it has no way
of figuring out what you sent. It has to believe you. When you lie to
printf, you get garbage results.
These are pretty fundamental C questions. You ought to be able to
answer these questions yourself before you start working on drivers.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.