Shop Learn
USB Transmit - Page 3 — Parallax Forums

USB Transmit

13»

Comments

  • Dave HeinDave Hein Posts: 6,347
    edited 2016-03-25 02:34
    jmg wrote: »
    Dave Hein wrote: »
    cluso, this C program gives the correct CRC for the sample messages given at
    If you run the CRC algorithm to the end of the Packet, including CRC (as received), does that sum to 0x00 ?
    No, including the CRC bytes does not produce 0.
    jmg wrote: »
    Dave Hein wrote: »
    If I try it with your data I don't get the same CRC.
    Does that mean a capture mistake ?
    Yes, it appears that there may be a capture mistake.

  • roglohrogloh Posts: 3,653
    edited 2016-03-25 02:32
    Cluso take a look through this if you haven't already - it may help you figure things out:

    http://www.usb.org/developers/docs/whitepapers/crcdes.pdf

    The CRC16 calculation does not include the DATA token or any SYNC, it runs from the bytes after the DATA0/DATA1 token to the end of the data packet. When I ran their two test samples through a table look up I was able to get the same result as them - see my earlier posts...
  • AribaAriba Posts: 2,549
    edited 2016-03-25 03:56
    Here is a testcode for CRC16. It uses the same data that Dave Hein used in the C example a few post before. So we can check the result easy.

    The crc calculation is made with 5 instructions, I think rogloh showed something similar (it depends a bit on the table).
    		getbyte tmp,crc,#0		'calc crc16
    		xor	tmp,data
    		rdlut	tmp,tmp			'3 cy
    		shr	crc,#8
    		xor	crc,tmp			'5 instr = 11 cy
    

    The attached code contains the 256 word table, and outputs the result as a hex-value.
    It shows $94B1, which is the same as in Dave Heins C code.

    Andy
  • roglohrogloh Posts: 3,653
    edited 2016-03-25 05:18
    By the way, I noticed there is a special case with USB when acting as the host and sending packets to a mixed speed hub (ie. something with both 1.5Mbps low speed and 12Mbps full speed devices attached downstream) where you would need to send out the special preamble PID at 12Mbps and then drop down to a lower speed rate at the host to continue to talk to your slow speed devices. This is because the USB hub is pass through not store and forward. I wonder if this is going to be possible or not with the clocking of the transmitter design Chip has. You would basically need to keep the transmit data going with the idle state added on the bus after the sync and preamble PID were sent at 12Mbps and then change the clock on the fly down to 1.5Mbps and continue with the next sync and PID byte in the middle of all this without generating the EOP until the end of this overall transfer, then switch back to 12Mbps. See section 8.6.5 of the USB2.0 spec for details.

    If dynamic rate adjust is not possible on the P2, then we can still talk to single devices such as keyboards and mice directly and to exclusive full speed or exclusive low speed hubs. It just means we could not support hubs with mixed speed devices attached. May not be a big deal if it cannot be achieved, but nice if it could be.

    The solution might just need some sort of divide by 8 circuit that can be re-configured on the fly while we are transmitting idles.

    Roger.

    Update: I guess the Rx path clock rate on a host also needs to be configurable to accept traffic at 1.5Mbps in preparation for the device response too. But at least it doesn't have to switch rates right in the middle of a packet, just in between packets whenever we are expecting data back from a low speed device, and we will know exactly when that is. Once the low speed packet comes back or we timeout when we don't get a response, we can switch back to receiving at 12Mbps.
  • cgraceycgracey Posts: 13,631
    rogloh wrote: »
    By the way, I noticed there is a special case with USB when acting as the host and sending packets to a mixed speed hub (ie. something with both 1.5Mbps low speed and 12Mbps full speed devices attached downstream) where you would need to send out the special preamble PID at 12Mbps and then drop down to a lower speed rate at the host to continue to talk to your slow speed devices. This is because the USB hub is pass through not store and forward. I wonder if this is going to be possible or not with the clocking of the transmitter design Chip has. You would basically need to keep the transmit data going with the idle state added on the bus after the sync and preamble PID were sent at 12Mbps and then change the clock on the fly down to 1.5Mbps and continue with the next sync and PID byte in the middle of all this without generating the EOP until the end of this overall transfer, then switch back to 12Mbps. See section 8.6.5 of the USB2.0 spec for details.

    If dynamic rate adjust is not possible on the P2, then we can still talk to single devices such as keyboards and mice directly and to exclusive full speed or exclusive low speed hubs. It just means we could not support hubs with mixed speed devices attached. May not be a big deal if it cannot be achieved, but nice if it could be.

    The solution might just need some sort of divide by 8 circuit that can be re-configured on the fly while we are transmitting idles.

    Roger.

    Update: I guess the Rx path clock rate on a host also needs to be configurable to accept traffic at 1.5Mbps in preparation for the device response too. But at least it doesn't have to switch rates right in the middle of a packet, just in between packets whenever we are expecting data back from a low speed device, and we will know exactly when that is. Once the low speed packet comes back or we timeout when we don't get a response, we can switch back to receiving at 12Mbps.

    You can change the NCO baud generator at any time via PINSETX.

    I'm putting up a new intermediate release v7z with the first-pass USB.
  • Cluso99Cluso99 Posts: 18,013
    WTG Chip. I will take a look as I think I must have a bit decoding error somewhere. Should be able to compare both to see what's up.

    BTW We need to be able to send out multiple SE0's when we are a host to cause reset, and detect this when a device (>2.5 bit times for a device). For host we could just temporarily disable smartpins to send out SE0's. Not sure about how to do this for a device.
  • roglohrogloh Posts: 3,653
    edited 2016-03-26 02:47
    cgracey wrote: »
    You can change the NCO baud generator at any time via PINSETX.

    I'm putting up a new intermediate release v7z with the first-pass USB.

    That's great. I wonder in this case if we will also have to switch the Smartpin mode to low speed host in the middle of this packet after the preamble, to switch the understanding of the D+/D- signalling levels with the J/K symbols? It was not 100% clear in the standard that you need to do this or if the hub transforms them it for you but it might be buried in there somewhere... USB sniffers attached to hubs could find this out. I hope the hub automatically does this for us - I expect it should but don't actually know.

    Update:
    Just found it in the USB2 spec. Section 11.8.4 on hub behaviour. Looks like we are golden.

    "When a low-speed device transmits, it does not preface its data packet with a PRE PID. Hubs will propagate upstream-directed packets of full-/low-speed using full-speed signaling polarity and edge rates.
    For both upstream and downstream low-speed data, the hub is responsible for inverting the polarity of the data before transmitting to/from a low-speed port."
  • Cluso99Cluso99 Posts: 18,013
    Success :)

    Found I was handling 0's and 1's incorrectly and inverted too.

    Both CRC5 & CRC16 now working correctly and the code I posted above works.

    Here is a transaction dump (snoop with P1) of LS with a MS Keyboard connected
    USB SNOOP v0.17a
    PID[D]=SETUP, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[3]=DATA0, 80 06 00 01 00 00 40 00, CRC16$94DD XOR$6B22 Calc$6B22 passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[B]=DATA1, 12 01 10 01 00 00 00 08, CRC16$7711 XOR$88EE Calc$88EE passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[3]=DATA0, 5E 04 52 07 10 01 01 02, CRC16$A713 XOR$58EC Calc$58EC passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[B]=DATA1, 00 01, CRC16$8F3F XOR$70C0 Calc$70C0 passed resid$0000
    PID[2]=ACK
    PID[1]=OUT, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[B]=DATA1,, CRC16$0000 XOR$FFFF Calc$FFFF passed resid$0000
    PID[2]=ACK
    PID[D]=SETUP, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[3]=DATA0, 00 05 17 00 00 00 00 00, CRC16$D3E9 XOR$2C16 Calc$2C16 passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$00, ENDP$0, CRC5$02 XOR$1D Calc$1D passed resid$00
    PID[B]=DATA1,, CRC16$0000 XOR$FFFF Calc$FFFF passed resid$0000
    PID[2]=ACK
    PID[D]=SETUP, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[3]=DATA0, 80 06 00 01 00 00 12 00, CRC16$F4E0 XOR$0B1F Calc$0B1F passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1, 12 01 10 01 00 00 00 08, CRC16$7711 XOR$88EE Calc$88EE passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[3]=DATA0, 5E 04 52 07 10 01 01 02, CRC16$A713 XOR$58EC Calc$58EC passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1, 00 01, CRC16$8F3F XOR$70C0 Calc$70C0 passed resid$0000
    PID[2]=ACK
    PID[1]=OUT, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1,, CRC16$0000 XOR$FFFF Calc$FFFF passed resid$0000
    PID[2]=ACK
    PID[D]=SETUP, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[3]=DATA0, 80 06 00 02 00 00 FF 00, CRC16$A4E9 XOR$5B16 Calc$5B16 passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1, 09 02 22 00 01 01 00 A0, CRC16$980A XOR$67F5 Calc$67F5 passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[3]=DATA0, 32 09 04 00 00 01 03 01, CRC16$4D35 XOR$B2CA Calc$B2CA passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1, 01 00 09 21 11 01 00 01, CRC16$9A57 XOR$65A8 Calc$65A8 passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[3]=DATA0, 22 41 00 07 05 81 03 08, CRC16$2389 XOR$DC76 Calc$DC76 passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1, 00 0A, CRC16$487E XOR$B781 Calc$B781 passed resid$0000
    PID[2]=ACK
    PID[1]=OUT, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[B]=DATA1,, CRC16$0000 XOR$FFFF Calc$FFFF passed resid$0000
    PID[2]=ACK
    PID[D]=SETUP, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[3]=DATA0, 80 06 00 03 00 00 FF 00, CRC16$64D4 XOR$9B2B Calc$9B2B passed resid$0000
    PID[2]=ACK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    PID[9]=IN, ADDR$17, ENDP$0, CRC5$11 XOR$0E Calc$0E passed resid$00
    PID[A]=NAK
    
    If you feed the CRC back into itself (ie you feed in the data and the crc received as well) the result in both CRC5 & CRC16 is $00 & $0000. This is contrary to that reported which claims the residual should be $0C & $800D respectively.
Sign In or Register to comment.