Author Topic: My OUT_PACKET variable gets filled  (Read 14226 times)

gi

  • Member
  • ***
  • Posts: 27
My OUT_PACKET variable gets filled
« on: October 10, 2012, 04:49:45 am »
Hi Jan,
I was trying to create a hid device using my Silabs F320 development board. The purpose is just to toggle a single LED on P0.0.
I have an application running in my PC to send the data.
1. If 0x31 was sent from PC to my development board, LED = ON.
2. If 0x30 is sent from PC to my development board, LED = OFF.

This was successful though. My problem was the variable (OUT_PACKET[8]) that holds the data (0x31 or 0x32).
This is how I declare it:

Code: [Select]
unsigned char OUT_PACKET[8] = {0,0,0,0,0,0,0,0};

When I send 0x31 to my board, OUT_PACKET gets filled with 8 1's. Same thing happens when I send 0x30.

I was expecting like this:

OUT_PACKET[0] = 49 //This index should only be filled with 0x31.
OUT_PACKET[1] = 48
OUT_PACKET[2] = 48
OUT_PACKET[3] = 48
OUT_PACKET[4] = 48
OUT_PACKET[5] = 48
OUT_PACKET[6] = 48
OUT_PACKET[7] = 48

This is how I call the reading process:
Code: [Select]
//USB ISR call this function
void Handle_Out1 ()
{
       .....

         Fifo_Read(FIFO_EP1, OUT_BUFFER.Length, (unsigned char*)OUT_PACKET);
   
       ......
}

//The Fifo_Read function
void Fifo_Read (unsigned char addr, unsigned int uNumBytes, unsigned char * pData)
{
   int i;

   if (uNumBytes)                      // Check if >0 bytes requested,
   {
      USB0ADR = (addr);                // Set address
      USB0ADR |= 0xC0;                 // Set auto-read and initiate
                                       // first read

      // Unload <NumBytes> from the selected FIFO
      for(i=0;i< (uNumBytes);i++)
      {
         while (USB0ADR & 0x80);       // Wait for BUSY->'0' (data ready)
         pData[i] = USB0DAT;           // Copy data byte
      }

      //while(USB0ADR & 0x80);         // Wait for BUSY->'0' (data ready)
      USB0ADR = 0;                     // Clear auto-read
   }
}

This is my HID Report Descriptor:
Code: [Select]
code const hid_report_descriptor HIDREPORTDESC =
{
    0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)   
    0x0a, 0x00, 0xaa,          // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)   
    0x0a, 0x01, 0xaa, // Usage (Vendor Usage 1)
    0x95, 0x01,                    //      REPORT_COUNT (1)
    0x75, 0x08,                    //      REPORT_SIZE (8)
    0x26, 0xff, 0x00,              //      LOGICAL_MAXIMUM (255)
    0x15, 0x00,                    //      LOGICAL_MINIMUM (0) 
    0x91, 0x02,                    //      OUTPUT (Data,Var,Abs)
    0x0a, 0x02, 0xaa,             //      USAGE (Vendor Usage 1)
    0x81, 0x02,                    //      INPUT (Data,Var,Abs)

    0xC0                            // Collection End
};

I really appreciate your help on this.

thanks in advance
gi

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: My OUT_PACKET variable gets filled
« Reply #1 on: October 10, 2012, 10:18:50 am »
I'm a little confused bec. you say the code works, but then explain why it doesn't.

At any rate, a hardware protocol analyzer would show what is transmitting on the bus. If you don't have an analyzer, use whatever debugging tools you have to find out what the host is actually sending, what the device endpoint is receiving, and what the device firmware is doing with received data.

For example, a software-only analyzer on the host can show the data being sent at the driver level.

Breakpoints, watch variables, etc. can show the data in the endpoint buffer.

What is the code that sends the data?

gi

  • Member
  • ***
  • Posts: 27
Re: My OUT_PACKET variable gets filled
« Reply #2 on: October 10, 2012, 12:06:26 pm »
Thank you Jan for your reply.

I actually done that, using usblyzer and I get this: 11111111 when my application in host PC send a single 0x31, 00000000 when sending 0x30.

I didn't program my development board to send a reply yet to host PC.
For simplicity, only an OUT is being sent.

In my main, I take the first index of OUT_PACKET[0] variable to see if I need to turn ON or OFF my LED, like this:
Code: [Select]
void main()
{
       while(1)
       {
            if(OUT_PACKET[0] == 0x31)
                   LED = ON;
            else if(OUT_PACKET[0] == 0x30)
                   LED = OFF;
       }
}


This works, however, the OUT_PACKET[0-7] was filled with 1's when I send a single 0x31 from my host PC.
OUT_PACKET[0-7] filled with 0's when I send a single 0x30 from my host PC.

When I send a single 0x31 from my PC to my board, I would like to have like this:
OUT_PACKET[0] = 1
OUT_PACKET[1] = 0
OUT_PACKET[2] = 0
OUT_PACKET[3] = 0
OUT_PACKET[4] = 0
OUT_PACKET[5] = 0
OUT_PACKET[6] = 0
OUT_PACKET[7] = 0

Am I missing something in report descriptor?

I hope I made this clear. Let me know if this wasn't clear enough.

Thank you again. I really appreciate your valuable response.
gi

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: My OUT_PACKET variable gets filled
« Reply #3 on: October 10, 2012, 12:37:29 pm »
What is the code that sends the data?

Tsuneo

  • Frequent Contributor
  • ****
  • Posts: 145
Re: My OUT_PACKET variable gets filled
« Reply #4 on: October 10, 2012, 01:04:31 pm »
Hi gi,

Code: [Select]
void Handle_Out1 ()
{
       .....

         Fifo_Read(FIFO_EP1, OUT_BUFFER.Length, (unsigned char*)OUT_PACKET);
   
       ......
}

The value of OUT_BUFFER.Length is suspicious.
Maybe, Fifo_Read() reads out more than the actual packet size, recieved by the endpoint?

In the SiLabs example, you'll see typical code around Fifo_Read()

Code: [Select]
USB_Bulk\F32x_USB_ISR.c

void BulkOrInterruptOut(PEP_STATUS pEpOutStatus)
{
   UWRITE_BYTE(INDEX, pEpOutStatus->bEp); // Index to current endpoint

         // Get packet length
         UREAD_BYTE(EOUTCNTL, bTemp);     // Low byte
         uBytes = (UINT)bTemp & 0x00FF;

         UREAD_BYTE(EOUTCNTH, bTemp);     // High byte
         uBytes |= (UINT)bTemp << 8;

            FIFORead(0x02, uBytes, &Buffer);

Tsuneo

Tsuneo

  • Frequent Contributor
  • ****
  • Posts: 145
Re: My OUT_PACKET variable gets filled
« Reply #5 on: October 10, 2012, 01:18:19 pm »
Ah, sorry
I didn't read your second post
Quote
I actually done that, using usblyzer and I get this: 11111111 when my application in host PC send a single 0x31, 00000000 when sending 0x30.
It's a problem of host side.

Tsuneo
« Last Edit: October 10, 2012, 11:27:25 pm by Tsuneo »

gi

  • Member
  • ***
  • Posts: 27
Re: My OUT_PACKET variable gets filled
« Reply #6 on: October 10, 2012, 11:21:13 pm »
Thank you Tsuneo.

I tried Jan's GenericHID application but it doesn't work, it always failed when tried to send a 1 or 0 or 31 or 30.
I noticed that it uses report ID in sending, correct me if I'm wrong with this.
I actually modified the Silab's sample firmware's hid report descriptor, see my first post. I remove the report ID on it.

Does the modified report descriptor affect the GenericHID application in sending OUT report?

thanks
gi


Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: My OUT_PACKET variable gets filled
« Reply #7 on: October 11, 2012, 10:23:49 am »
The HID descriptor declares report IDs only if at least one report type has more than one report.

Windows applications always provide a report ID as the first byte in reports to send.

Reports received by Windows applications always contain a report ID as the first byte.

The report ID travels on the bus only if the report ID > 0.

If the report ID is zero, the HID driver removes the report ID before sending the data and adds the report ID to received data.

You're using my Generic HID application and the host is sending FFh when it should send 31h?

Show the code that is filling the Write buffer and sending the data.

gi

  • Member
  • ***
  • Posts: 27
Re: My OUT_PACKET variable gets filled
« Reply #8 on: October 12, 2012, 01:49:26 am »
Hi Jan,

It is not ffh, its 1 or 31h that filled in uchar OUT_PACKET.

I think I found the cause of it. This is what Tsuneo pointed out on his first reply I believed.

This is what it does:

1. Host PC send single byte 31h to my board.

2. My board handles the OUT packet (see below code snippet), where it calls the Setup_OUT_BUFFER function.

3. In my Setup_OUT_BUFFER function I set the OUT_BUFFER.Ptr = OUT_PACKET  &  OUT_BUFFER.Length = 8 and this is the 2nd Fifo_Read function's parameter passed to it (unsigned int uNumBytes).

4. In Fifo_Read, it loops 8x, and this is where the OUT_PACKET gets filled with 1's or 31h.

My assumption after this situation was (don't know if this apply to all USB MCU and correct me if I'm wrong with this):

USB0DAT (USB0 Data) register will not be cleared after the first read until a new data in fifo is ready (I search the datasheet but couldn't find the specific).

In my case I'm only sending a single byte (31h) and it remains in fifo forever. This is the reason why I get 8 1s, in every iteration USB0DAT contains 1.

Also, I noticed that the Length of OUT_BUFFER.Length should equal to the report count of my report descriptor which equals to 1.

Am I correct with all of these?

Code: [Select]

void Handle_Out1 ()
{

     .......

      Setup_OUT_BUFFER ();             // Configure buffer to save
                                                 // received data
      Fifo_Read(FIFO_EP1, OUT_BUFFER.Length, (unsigned char*)OUT_PACKET);

      ....

   }
}

//Initialize the buffer pointer and its expected size to be receive
void Setup_OUT_BUFFER(void)
{
OUT_BUFFER.Ptr = OUT_PACKET;
    OUT_BUFFER.Length = 8;             //This should be 1, so the fifo read iterates only once and my OUT_PACKET won't get filleds with 8 1s.
}

//The Fifo_Read function
void Fifo_Read (unsigned char addr, unsigned int uNumBytes, unsigned char * pData)
{
   int i;

   if (uNumBytes)                      // Check if >0 bytes requested,
   {
      USB0ADR = (addr);                // Set address
      USB0ADR |= 0xC0;                 // Set auto-read and initiate
                                       // first read

      // Unload <NumBytes> from the selected FIFO
      for(i=0;i< (uNumBytes);i++) //<------------------------uNumBytes was set to 8 and so it loops 8x all 1s------------->
      {
         while (USB0ADR & 0x80);       // Wait for BUSY->'0' (data ready)
         pData[i] = USB0DAT;           // Copy data byte
      }

      //while(USB0ADR & 0x80);         // Wait for BUSY->'0' (data ready)
      USB0ADR = 0;                     // Clear auto-read
   }
}

thanks in advance.
gi

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: My OUT_PACKET variable gets filled
« Reply #9 on: October 12, 2012, 09:31:31 am »
Yes, prepare the data to send and write it once to the endpoint's buffer.

gi

  • Member
  • ***
  • Posts: 27
Re: My OUT_PACKET variable gets filled
« Reply #10 on: October 14, 2012, 08:49:34 pm »
Thank you very much Jan.